您的位置:首页 > 其它

【算法基础个人常用总结】<-------持续更新------->

2016-05-04 17:31 507 查看
很多东西久不用了,原本再熟悉也是会忘记的,现在可算是体会到了,记录下来常用的基础知识,方便日后再捡起来,加油。


<-------持续更新------->
<-------持续更新------->
<-------持续更新------->

一个正在努力的小伙子

# 二叉树,节点指针数据类型,先序遍历,中序遍历(加一个路径栈记录往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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: