【算法基础个人常用总结】<-------持续更新------->
2016-05-04 17:31
507 查看
很多东西久不用了,原本再熟悉也是会忘记的,现在可算是体会到了,记录下来常用的基础知识,方便日后再捡起来,加油。
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
一个正在努力的小伙子
# 二叉树,节点指针数据类型,先序遍历,中序遍历(加一个路径栈记录往L还是往R扩展,方便手工画出二叉树)
#
# 二分搜索
#
# 常用数据结构,priority_queue的常用功能,优先队列,一次查找时间复杂度为logN, 前k大数
#
# 更新priority_queue
#
# 常用数据结构,map的常用功能,hash功能,打表,下标离散不连续,且个数也是未知的
#
# 常用数据结构,vector的常用,链表功能,主要是数组长度不固定
#
# 计时,打印时间
#
# 读入字符串:1》按空格、回车等分隔读字符串,2》 读整行字符串(包括空格)
#
# 读文件,写文件,和控制台IO的切换
#
# 完全copy一个文件,包括空行,空格,回车,全部一样
#
# 浮点数问题,四舍五入,double不用==,double用作差绝对值绝对值,浮点数绝对值fabs
#
# 取对数精度问题
# 字符串转数字,数字转字符串。string 和 int 之间的转化,当返回值不是基础数据类型的时候,用自定义数据类型封装
#
# 自己实现的快排,递归形式
#
# 第K大数,快排的思想用来求第K大数,或者用来求中位数,时间复杂度为O(n), 因为F(n) = F(n / 2) + O(n分 + 1合并),故F(n) = O(n)
#
# 排序
#
# 数学相关,最大公约数,最小公倍数
#
# 素数筛选法,一般结合二分搜索
#
# 全排列,DFS,用数组模拟栈
#
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
@RunningZ
<-------持续更新------->
<-------持续更新------->
一个正在努力的小伙子
# 二叉树,节点指针数据类型,先序遍历,中序遍历(加一个路径栈记录往L还是往R扩展,方便手工画出二叉树)
/** 1) 二叉树结构: node0 / \ node1 node2 / \ / \ node3 node4 node5 node6 / \ / \ / \ / \ NULL N N N N N N N 2) ******* 关键 ******* 把 node0 / \ 看成一个单元,则根节点,树节点,叶节点,都统一起来了。 3) 插入第一个元素前 NULL 插入第一个元素后 node0 / \ */ #include<stdio.h> #include<stdlib.h> struct Node { int data; Node* l; Node* r; }; void insert(Node* &root, Node* node) { // Node* &root, 要改变root自身的值必须&引用数据类型 // Node* node, 要改变的是node指针指向的值,例如node->data的值,则直接Node* 即可 if (root == NULL) { root = node; return; } if (node->data <= root->data) { insert(root->l, node); } else { insert(root->r, node); } } // 先序遍历: l, M, R void showTree(Node* root){ if (root == NULL) return; showTree(root->l); printf("%d ", root->data); showTree(root->r); } // 中序遍历: M, L, R // 加一个路径记录是扩展左还是右节点,方便画出二叉树 void showTree2(Node* root, char path[], int pi){ if (root == NULL) return; printf("%d# ", pi); for (int i = 0; i < pi; i++) { printf("%c ", path[i]); } printf("%d \n", root->data); path[pi++] = 'L'; showTree2(root->l, path, pi); pi--; path[pi++] = 'R'; showTree2(root->r, path, pi); pi--; } int main() { int i, n; n = 20; Node* root = NULL; // add elements for (i = 0; i < n; i++) { int data = rand() % n; printf("%d ", data); Node* node = (Node*)malloc(sizeof(Node)); // 动态分配空间,相当于new一个对象 node->data = data; node->l = NULL; node->r = NULL; insert(root, node); } printf("\n"); // show the tree char path[40]; int pi = 0; showTree(root); printf("\n"); showTree2(root, path, pi); return 0; }
#
# 二分搜索
#include<stdio.h> int bSearch(int a[], int l, int r, int key) { int mid; while (l <= r) { mid = (l + r) >> 1; if (key == a[mid]) return mid; if (key < a[mid]) { r = mid - 1; } else { l = mid + 1; } } return -1; } int main() { int a[1024]; int i, n; n = 1024; for (i = 0; i < n; i++) { a[i] = i; } int key = 7; int index = bSearch(a, 0, n - 1, key); printf("index = %d\n", index); return 0; }
#
# 常用数据结构,priority_queue的常用功能,优先队列,一次查找时间复杂度为logN, 前k大数
#include<stdio.h> #include<queue> #include<vector> #include<stdlib.h> using namespace std; struct Node { int x; int y; }; struct cmp { bool operator()(const Node n1, const Node n2) { if (n1.x != n2.x) { return n1.x > n2.x; // ascending by x } else { return n2.y > n2.y; // ascending by y when n1.x == n2.x } } }; priority_queue<Node, vector<Node>, cmp> myQueue; int main() { int i, n; n = 10; // add elements for (i = 0; i < n; i++) { int x = rand() % n; int y = rand() % n; printf("%d,%d ", x, y); Node node; node.x = x; node.y = y; myQueue.push(node); } printf("\n"); // print all elements while (!myQueue.empty()) { Node node = myQueue.top(); myQueue.pop(); printf("%d,%d ", node.x, node.y); } printf("\n"); return 0; }
#
# 更新priority_queue
#include<stdio.h> #include<vector> #include<queue> using namespace std; struct Node { int x; }; struct cmp{ bool operator()(const Node* n1, const Node* n2) { return n1->x >= n2->x; } }; int main() { priority_queue<Node*, vector<Node*>, cmp> myQueue; Node* node1 = (Node*)malloc(sizeof(Node)); Node* node2 = (Node*)malloc(sizeof(Node)); Node* node3 = (Node*)malloc(sizeof(Node)); node1->x = 1; node2->x = 2; node3->x = 3; node2->x = 2222222; // delete // dynamic update Node* tmp = myQueue.top(); myQueue.pop(); myQueue.push(tmp); return 0; }
#
# 常用数据结构,map的常用功能,hash功能,打表,下标离散不连续,且个数也是未知的
#include<stdio.h> #include<map> #include<string.h> #include<string> #include<stdlib.h> #include<iostream> using namespace std; struct cmp { bool operator()(const int x1, const int x2) { return x1 > x2; } }; map<int, int> m1; map<int, string> m2; map<string, int> m3; int main() { int i, n; n = 10; // <int, int> // add elements for (i = 0; i < n; i++) { int key = i; m1[key] = i + 100; } // delete elements in m m1.erase(1); // by key // upper_bound, << key < 返回的下标的指针 printf("upper_bound = %d\n", *m1.upper_bound(3)); // 1, 2, 3, 3, 3, 3, 3, 4 @ 返回的是最后一个3的下标 + 1 // lower_boudd, < key <= 返回的下标的指针 printf("lower_bound = %d\n", *m1.lower_bound(3)); // 1, 2, 3, 3, 3, 3, 3, 4 @ 返回的是第一个3的下标 // juedging whether m contains a key int key = 77; if (m1.count(key) != 0) { printf("m1 contains %d\n", key); } else { printf("m1 doesn't contain %d\n", key); } // travel all elements, which is sorted by key in m1 map<int,int>::iterator it1; for (it1 = m1.begin(); it1 != m1.end(); it1++) { printf("m[%d]=%d ", it1->first, it1->second); } printf("\n"); // <int, string> // char[] 可以当string用,但是string不能能char[]用 char cs[] = "charArrayString"; m2[1] = cs; // printf("%s\n", m2[1]); // Runtime Error, 因为m2[1]拿到的是string类型,不是char[]类型 cout << m2[1] << endl; // use cout to print string for (i = 0; i < m2[1].size(); i++) { printf("%c", m2[1].at(i)); } printf("\n"); // <string, int> char cs2[] = "bbb"; m3[cs2] = 222; printf("cs[], %d\n", m3["bbb"]); // char[] can auto convert to string string str2 = "bbb"; printf("string, %d\n", m3[str2]); <span style="white-space:pre"> </span>printf("========== m customed sort\n"); map<int, int, cmp> m; // m不能使用erase m[2] = 22; m[3] = 33; m[1] = 11; map<int, int, cmp>::iterator it; for (it = m.begin(); it != m.end(); it++) { printf("%d,%d ", it->first, it->second); } return 0; }
#
# 常用数据结构,vector的常用,链表功能,主要是数组长度不固定
#include<stdio.h> #include<vector> using namespace std; struct Node { int x; int y; }; vector<int> list1; vector<Node> list2; int main() { int i, n; n = 10; // 初始化 list1.clear(); // 添加元素 for (i = 0; i < n; i++) { list1.push_back(i); } // 在第k个位置插入一个值 int k = 0; vector<int>::iterator it = list1.begin() + k; // + 被重载了 list1.insert(it, -1); // 删除元素 list1.erase(it); // it是指针参数 // list1.erase(list1.end() - 1); // list1.pop_back(); // 删除最后一个元素,两个等价 // 遍历 int len1 = list1.size(); for (i = 0; i < len1; i++) { printf("%d ", list1[i]); // list1[i] 等价 list1.at(i)) } printf("\n"); // 自定义数据类型 for (i = 0; i < n; i++) { Node node; node.x = i; node.y = 2 * i; list2.push_back(node); } int len2 = list2.size(); for (i = 0; i < len2; i++) { printf("%d,%d ", list2[i].x, list2[i].y); } printf("\n"); return 0; }
#
# 计时,打印时间
#include<stdio.h> #include<time.h> int main() { clock_t t1 = clock(); int i, n; n = 1e9; int sum = 1; for (i = 0; i < n; i++) { sum = sum + i; } clock_t t2 = clock(); printf("time = %d\n", t2 - t1); return 0; }
#
# 读入字符串:1》按空格、回车等分隔读字符串,2》 读整行字符串(包括空格)
#include<stdio.h> #include<string.h> #include<string> char str[100]; int main() { int i, n; scanf("%d", &n); printf("n = %d\n", n); for (i = 0; i < n; i++) { scanf("%s", str); // 读字符串,以空格,制表符,回车等为分界线 printf("%s\n", str); printf("length = %d\n", strlen(str)); } getchar(); // 如果再gets之前用过scanf,那么在gets之前需要getchar把当前行的回车吸收掉,到下一行 gets(str); // 读一整行,包括空格 printf("%s", str); return 0; }
#
# 读文件,写文件,和控制台IO的切换
#include<stdio.h> char str[100]; int main() { // file freopen("in.txt", "r", stdin); scanf("%s", &str); freopen("out.txt", "w", stdout); printf("%s", str); // console freopen("con", "r", stdin); scanf("%s", &str); freopen("con", "w", stdout); printf("%s", str); return 0; }
#
# 完全copy一个文件,包括空行,空格,回车,全部一样
#include<stdio.h> char str[100]; int main() { freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); int flag = 0; while(gets(str) != NULL) { // gets一次读一行,会把空行,空格都会读进来, if (flag++ > 0) printf("\n"); printf("%s", str); } return 0; }
#
# 浮点数问题,四舍五入,double不用==,double用作差绝对值绝对值,浮点数绝对值fabs
#include<stdio.h> #include<math.h> int main() { double d1 = 7.00000000001; double d2 = 6.9999999; int d1Int = (int)(d1 + 0.5); // 四舍五入 int d2Int = (int)(d2 + 0.5); printf("%.15f %d\n", d1, d1Int); // %f只保留6位, printf("%f %d\n", d2, d2Int); // fabs浮点数绝对值 if (fabs(d1 - d1Int) < 1e-6) { //1e-6 = 0.000001, double不能用==,应该用绝对值小于一个足够小的数 printf("777\n"); } return 0; }
#
# 取对数精度问题
// e = (int)log5(n) #include<stdio.h> #include<math.h> int main() { int n1 = 625; int n2 = 626; int n = n1; // double d1 = log(n) / log(5); int i1 = d1; printf("%d\n", i1); // 3 wrong answer // n1 ~= n2, e1 == e2 // so we compare n1 and n2 _int64 ni = 1; int ei = -1; while (ni <= n) { // find the first ni > n ni *= 5; ei++; } printf("%d\n", ei); return 0; }
# 字符串转数字,数字转字符串。string 和 int 之间的转化,当返回值不是基础数据类型的时候,用自定义数据类型封装
#include<stdio.h> #include<string.h> #include<string> #include<iostream> using namespace std; struct Node{ char cs[20]; }; // 当想返回的值不是基础数据类型的时候,用结构体封装 Node num2str(int n) { Node node; sprintf(node.cs, "%d", n); return node; } int str2num(char s[]) { int n = atoi(s); return n; } int main() { int n = 777; printf("str = %s\n", num2str(n).cs); char cs[10]; scanf("%s", cs); printf("num = %d\n", str2num(cs)); // char []可以直接当string使用,string当char[]使用只能str.at(i) char cs2[] = "RunningZ"; string str = cs2; cout << cs2 << endl; cout << str << endl; return 0; }
#
# 自己实现的快排,递归形式
#include<stdio.h> #include<time.h> #include<stdlib.h> #include<algorithm> using namespace std; int a[2222222]; void qSort(int a[], int l, int r) { if (l >= r) return; int pl = l; int pr = r; int tmp = a[pl]; while (pl < pr) { // 是 <, 而不是<= while (pl < pr && a[pr] >= tmp) pr--; if (pl >= pr) break; // 注意 a[pl++] = a[pr]; while (pl < pr && a[pl] <= tmp) pl++; if (pl >= pr) break; a[pr--] = a[pl]; } a[pl] = tmp; qSort(a, l, pl - 1); qSort(a, pl + 1, r); } int main() { int i, n; n = 2222222; for (i = 0; i < n; i++) { a[i] = rand() % n; } clock_t t1 = clock(); //sort(a, a + n); qSort(a, 0, n - 1); clock_t t2 = clock(); printf("time = %d\n", t2 - t1); return 0; }
#
# 第K大数,快排的思想用来求第K大数,或者用来求中位数,时间复杂度为O(n), 因为F(n) = F(n / 2) + O(n分 + 1合并),故F(n) = O(n)
#include<stdio.h> #include<stdlib.h> #include<time.h> #include<algorithm> using namespace std; int a[5000001]; int getMedian(int a[], int l, int r, int k) { // printf("l = %d, r = %d, k = %d\n", l, r, k); if (l == r && k == 0) return a[l]; int pl = l; int pr = r; int tmp = a[l]; while (pl < pr) { while (pl < pr && a[pr] > tmp) pr--; if (pl >= pr) break; a[pl++] = a[pr]; while (pl < pr && a[pl] < tmp) pl++; if (pl >= pr) break; a[pr--] = a[pl]; } a[pl] = tmp; if(pl - l == k) return tmp; if(pl - l > k) { return getMedian(a, l, pl - 1, k); } else { return getMedian(a, pl + 1, r, k - (pl - l + 1)); } } int main() { int i, n; n = 5000000; for (i = 0; i < n; i++) { a[i] = rand() % n; //printf("%d ", a[i]); } //printf("\n"); clock_t t1 = clock(); int median = getMedian(a, 0, n - 1, n / 2); printf("median = %d\n", median); clock_t t2 = clock(); printf("time1 = %d\n", t2 - t1); t1 = clock(); sort(a, a + n); printf("sort mid = %d\n", a[n>>1]); t2 = clock(); printf("time2 = %d\n", t2 - t1); }
#
# 排序
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; struct Node { int x; int y; }; int a[101]; Node node[101]; bool cmp1(const int x1, const int x2) { // 递增 return x1 < x2; } bool cmp2(const Node n1, const Node n2) { // 递减 if (n1.x != n2.x) return n1.x > n2.x; return n1.y > n2.y; } int main() { int i, n; n = 10; for (i = 0; i < n; i++) { a[i] = rand() % 10; // 基本数据类型 node[i].x = rand() % 10; // 自定义数据类型 node[i].y = rand() % 10; } sort(a, a + n, cmp1); // 数组头,数组头 + 个数,比较函数 sort(node, node + n, cmp2); // 加法已经重载 for (i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); for (i = 0; i < n; i++) { printf("%d,%d ", node[i].x, node[i].y); } printf("\n"); return 0; }
#
# 数学相关,最大公约数,最小公倍数
#include<stdio.h> int gcd(int n1, int n2) { int nMax = n1 > n2 ? n1 : n2; int nMin = n1 < n2 ? n1 : n2; if (nMax % nMin == 0) return nMin; return gcd(nMax % nMin, nMin); } int main() { int n1, n2; n1 = 12; n2 = 16; // 最大公约数 int n12 = gcd(n1, n2); printf("%d\n", n12); // 最小公倍数 int nn = n1 / gcd(n1, n2) * n2; printf("%d\n", nn); return 0; }
#
# 素数筛选法,一般结合二分搜索
#include<stdio.h> #include<math.h> int a[1000001]; int prime[1000001]; int pi = 0; void getPrime() { int i, j, n; n = 100; a[0] = 1; a[1] = 1; for (i = 3; i <=n; i++) { a[i] = i % 2 == 0 ? 1 : 0; } int sqrtN = sqrt(n); for (i = 3; i < sqrtN; i++) { if (a[i] != 0) continue; for (j = i * i; j <= n; j += i) { a[j]++; } } int count = 0; for (i = 0; i <= n; i++) { if (a[i] == 0) { count++; prime[pi++] = i; // printf("%d ", i); } } printf("count = %d\n", count); } int main() { getPrime(); return 0; }
#
# 全排列,DFS,用数组模拟栈
#include<stdio.h> int used[20]; int stack[20]; int top = 0; void permutation(int n, int deep) { int i; if (deep == n) { for (i = 0; i < top; i++) { printf("%d ", stack[i]); } printf("\n"); return; } for (i = 1; i <= n ;i++) { if (used[i] == 1) continue; used[i] = 1; stack[top++] = i; permutation(n, deep + 1); stack[top--] = 0; used[i] = 0; } } void init(int n) { int i; for (i = 1; i <= n; i++) { used[i] = 0; } top = 0; } int main() { // freopen("out.txt", "w", stdout); // n = 7时,输出文件大小(7 * 2 + 2) * 7! = 80640 Byte, 数字在文件里存成0~9的字符,每一位占1个字节,回车占两个字节 int i, n; n = 7; init(n); permutation(n, 0); return 0; } // 2016-5-9 12:43:37
#
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
<-------持续更新------->
@RunningZ
相关文章推荐
- 为什么JAVA中的属性不能覆盖而方法却可以覆盖
- IOS中UITextView(多行文本框)控件的简单用法
- iOS安装CocoaPods
- zBar解码中文乱码
- 更新mac系统和更新到Xcode7.3版本出现的: cannot create __weak reference in file using manual reference counting
- jmeter 打不开 提示“Not able to find Java executable or version”的解决办法
- 第十周
- (转载)JavaWeb学习总结(五十一)——邮件的发送与接收原理
- tinyhttp源码阅读(注释)
- 如何理解子网掩码中的“子网”?
- 如何用ssh挂载远程目录
- size_t 与 ssize_t 类型
- 十九、享元模式Flyweight(结构型模式)
- Oracle 唯一化排序分页查询只显示第一页
- iOS开发中@interface 和 @implementation区别, @property 和@synthesize区别
- 以usb-modeswitch配华为LTE上网卡EC5373在Linux下试图上网的尝试
- 自定义的AlertDialog(shape,selector)
- Android EditText 自定义
- THINKPHP快速创建分页
- STM8 GPIO模式