很多東西久不用了,原本再熟悉也是會忘記的,現在可算是體會到了,記錄下來常用的基礎知識,方便日後再撿起來,加油。
# 二叉樹,節點指針數據類型,先序遍歷,中序遍歷(加一個路徑棧記錄往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