基础算法总结
#include <iostream> using namespace std; //-----------LinkedList API------------- typedef struct ListNode { int key; struct ListNode * next; struct ListNode * prev; }ListNode; #define LISTSIZE 1000 ListNode ListNodePool[LISTSIZE]; int NodeNum = 0; ListNode NIL; ListNode * getNewNode(){ return & ListNodePool[NodeNum++]; } void listInit(){ NIL.next = &NIL; NIL.prev = &NIL; NIL.key = 0; } void listInsertAtFront(ListNode * node){ node->next = NIL.next; node->prev = &NIL; NIL.next->prev = node; NIL.next = node; } void listInsertAfter (ListNode * dstNode, ListNode * NewNode){ NewNode->next = dstNode->next; NewNode->prev = dstNode; dstNode->next->prev = NewNode; dstNode->next = NewNode; } void listDelete(ListNode * node){ node->prev->next = node->next; node->next->prev = node->prev; } ListNode * listSearch(int k){ ListNode * x = NIL.next; while(x != &NIL && x->key != k){ x = x->next; } return x; } //end of LinkedList API int data[LISTSIZE]; void insertSort(int data[], int N){ for(int i = 1; i < N; i++){ int key = data[i]; int j; for(j = i - 1; j >= 0; j--){ if(data[j] > key){ data[j + 1] = data[j]; }else{ break; } } data[j + 1] = key; } } void showData(int N){ for(int i = 0; i < N; i++){ cout << data[i] << " "; } cout << endl; } void showList(){ ListNode * curNode = NIL.next; while(curNode != & NIL){ cout << curNode->key << " "; curNode = curNode->next; } cout << endl; } void listInsertSort(){ ListNode * curNode = NIL.next->next; ListNode * tmpNode; while(curNode != &NIL){ //cout << curNode->key << " " << endl; ListNode * dstNode = NIL.next; while(dstNode != curNode && dstNode->key < curNodekey){ dstNode = dstNode->next; } dstNode = dstNode->prev; tmpNode = curNode->next; listDelete(curNode); listInsertAfter(dstNode, curNode); curNode = tmpNode; } } void main(){ freopen("input.txt", "r", stdin); int N; cin >> N; for(int i = 0; i < N; i++){ cin >> data[i]; cout << data[i] << " " ; } cout << endl; listInit(); ListNode * dstNode = &NIL; for(int i = 0; i < N; i++){ ListNode * node = getNewNode(); node->key = data[i]; listInsertAfter(dstNode, node); dstNode = dstNode->next; } ListNode * curNode = NIL.next; while(curNode != &NIL){ cout << curNode->key << " "; curNode = curNode->next; } cout << endl; insertSort(data, N); showData(N); listInsertSort(); showList(); } //--------STACK API-------- #define STACK_SIZE 100000 //根据需要更改 typedef struct Element{ int x; int y; }Element; Element Stack[STACK_SIZE]; int top = 0; void stackInit(){ top = 0; } bool isEmpty(){ return top; } Element pop(){ return Stack[top--]; } void push(Element e){ Stack[top++] = e; } Element getTop(){ return Stack[top]; } //end of stack API //------------QUEUE API------------- #define QUEUE_SIZE 100000 Element Queue[STACK_SIZE]; int front = 0; int rear = 0; void queueInit(){ front = rear = 0; } bool isEmpty(){ return front==rear; } void enQueue(Element e){ Queue[rear++] = e; } Element deQueue(){ return Queue[front++]; } Element getFront(){ return Queue[front]; } //Heap API #include <iostream> using namespace std; //根据需求调整大小 #define SIZE 1001 int heap[SIZE]; #define swap(x, y) {x = x + y; y = x - y; x = x - y;} void fixDown(int heap[], int pos, int size){ int x = pos; if(x > size) return;//exit // 选出最大的 int l = 2 * x; int r = l + 1; int maxPos = x; if(l <= size && heap[maxPos] < heap[l]) maxPos = l; if(r <= size && heap[maxPos] < heap[r]) maxPos = r; if(maxPos != x){ //如果父节点不是最大的, 进行互换, 并在新的点上继续fixDown swap(heap[x], heap[maxPos]); fixDown(heap, maxPos, size); } } void fixUp(int heap[], int size, int pos){ int x = pos; int p; while(x > 1){ p = x/2; if(heap[x] > heap[p]){ swap(heap[x], heap[p]); x = p; }else return; } } void buildHeap(int heap[], int size){ for(int i = size/2; i >= 1; i--){ fixDown(heap, i, size); } } //heapSort前要先build heap void heapSort(int heap[], int size){ int oriSize = size; for(int i = 0; i < oriSize - 1; i++){ //注意不要把oriSize和size混在一起 //互换堆顶和最后一个元素,将堆顶元素放在数组最后面 swap(heap[size], heap[1]); size--; fixDown(heap, 1, size); } } int main(){ int size = 7; for(int i = 1; i <= size; i++) heap[i] = 8 - i; buildHeap(heap, size); heap[size + 1] = 8; size++; fixUp(heap, size, size); heapSort(heap, size); } //哈希:用于进行信息的快速查找 // 1. 提取信息的特征值 // 2. 将特征值和信息的存储地址进行关联 #include <iostream> using namespace std; #define SIZE 100000 //根据需要更改 typedef struct Node{ int key; struct Node * next; struct Node * prev; }Node; Node HashTable[SIZE + 10]; Node HashPool[SIZE+10]; //根据题意判断需不需要hashpool int HashIndex = 0; Node * getNewNode(){ return &HashPool[HashIndex++]; } void insertNode(int key, Node * newNode){ Node * head = &HashTable[key]; newNode->prev = head; newNode->next = head->next; head->next = newNode; newNode->next->prev = newNode; } void initHash(int N){ HashIndex = 0; //reset hash pool for(int i = 0; i < N; i++){ HashTable[i].prev = &HashTable[i]; HashTable[i].next = &HashTable[i]; } } int getKey(int val){ return val % (SIZE + 3); } Node * searchNode(Node * node){ int key = getKey(node->key); Node * x = HashTable[key].next; while(x != &HashTable[key] && x->key != node->key){ x = x->next; } if(x != &HashTable[key]) return x; else return NULL; } void deleteNode(Node * node){ node->prev->next = node->next; node->next->prev = node->prev; } int main(){ initHash(100); for(int i = 0; i < 100; i++){ Node * newNode = getNewNode(); newNode->key = i; int hashKey = getKey(i); insertNode(hashKey, newNode); Node * node = searchNode(newNode); cout << node->key << endl; } return 0; } //二分查找 int bisearch(int number[], int find) { int low, mid, upper; low = 0; upper = MAX - 1; while(low <= upper) { mid = (low+upper) / 2; if(number[mid] < find) low = mid+1; else if(number[mid] > find) upper = mid - 1; else return mid; } return -1; } //快速排序 void quicksort(int left,int right) { int i,j,t,temp; if(left>right) return; temp=a[left]; //temp中存的就是基准数 i=left; j=right; while(i!=j) { //顺序很重要,要先从右边开始找 while(a[j]>=temp && i<j) j--; //再找右边的 while(a[i]<=temp && i<j) i++; //交换两个数在数组中的位置 if(i<j){ t=a[i]; a[i]=a[j]; a[j]=t; } } //最终将基准数归位 a[left]=a[i]; a[i]=temp; quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程 quicksort(i+1,right);//继续处理右边的, 这里是一个递归的过程 } //二叉树: 基本性质: 性质1:二叉树第i层上的结点数目最多为 2{i-1} (i≥1)。 性质2:深度为k的二叉树至多有2{k}-1个结点(k≥1)。 性质3:包含n个结点的二叉树的高度至少为log2 (n+1)。 性质4:在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1。 //二叉搜索树 #include<iostream> using namespace std; struct node{ int val; node *lch, *rch, *parent; }; //插入节点 node *insert(node *p, int x){ if( p == NULL){ //node *q = new node; node *q = (node *)malloc(sizeof(node)); q->val = x; q->lch = q->rch = NULL; return q; }else{ if( x < p->val ) p->lch = insert(p->lch, x); else p->rch = insert(p->rch, x); return p; } } //查找节点 node *find(node *p, int x){ if( p == NULL || p->val == x) return p; //递归 if( x < p->val) find(p->lch, x); else find(p->rch, x); //非递归 while((p != NULL) && (p->val != x)){ if( x < p->val) p = p->lch; else p = p->rch; } return p; } //删除节点,返回根节点 node *remove(node *p, int x){ if( p == NULL) return NULL; else if( x < p->val) p->lch = remove( p->lch, x); else if( x > p->val) p->rch = remove(p->rch, x); else if( p->lch == NULL){ node *q = p->rch; delete p; return q; } else if(p->lch->rch == NULL){ node *q = p->lch; q->rch = p->rch; delete p; return q; } else{ //左右都不为空 node *q; for( q = p->lch; q->rch->rch != NULL; q= q->rch); //把需要删除节点的左儿子子孙中的最大值提到删除节点位置 node * r = q->rch; q->rch = r->lch;//提升节点的左子树作为其父节点右子树 r->lch = p->lch; r->rch = p->rch; delete p; return r; } return p; } //前中后序遍历 node *maximum(node *node){ if(node == NULL) return NULL; while(node->rch != NULL) node = node->rch; return node; } node *minimum(node *node){ if(node == NULL) return NULL; while(node->lch != NULL) node = node->lch; return node; } //前驱和后继节点( 中序遍历 ) node *predecessor(node *x){ //x存在左孩子,前驱为"以其左孩子为根的树的最大节点" if( x->lch != NULL) return maximum(x->lch); //x不存在左孩子,前驱为: // 1)x是"一个右孩子",则"x的前驱结点"为 "它的父结点" // 2)x是"一个左孩子",则查找"x的最低的父结点,并且该节点作为该父结点右孩子",找到的这个"最低的父结点"就是"x的前驱结点" node *y = x->parent; while( (y != NULL) && (x == y->lch)){ x = y; y = y->parent; } return y; } node *successor(node *x){ //x存在右孩子,前驱为"以其右孩子为根的树的最小节点" if(x->rch != NULL) return minimum(x->rch); //x不存在右孩子: //1)x是"一个左孩子",则"x的后继结点"为 "它的父结点" //2)x是"一个右孩子",则查找"x的最低的父结点,并且该节点作为该父结点左孩子",找到的这个"最低的父结点"就是"x的前驱结点" node *y = x->parent; while(( y != NULL )&&(x == x->rch)){ x = y; y = y->parent; } return y; }
//单源最短路径问题(Dijikstra算法)
//N : 结点数量
//source: 起始结点下标
int matrix[N][N]; //存储图的二维数组 boolean flagFinal[N]; //标志位 flagFinal[i]为 true //代表从 source 源点到 i 结点的最短路径已经计算得到 int result[N]; //存储最终结果 result[i]代表从 source 源点到 i 结点最短路径的值 void Dijkstra() { //初始化赋值 for (int i = 1; i <= N; i++) { result[i] = matrix[source][i]; flagFinal[i] = false; } //起始结点特殊处理 (到自身无需计算) result[source] = 0; flagFinal[source] = true; //遍历 N-1 次 for (int count = 1; count < N; count++) { //从剩余结点中,寻找距离 source 点最短的结点 //记录其下标 minDisLoc int tmpDis = INF; int minDisLoc = 0; //初始化下标为 0 (结点下标 1...N ) for (int i = 1; i <= N; i++) { if ((false == flagFinal[i]) && (result[i] < tmpDis)) { tmpDis = result[i]; minDisLoc = i; } } //找到本轮距离 source 最短的结点 下标 minDisLoc if (minDisLoc != 0) //更新 minDisLoc 结点标志位 { flagFinal[minDisLoc] = true; //更新各个结点的 result(距离 source 源点的距离) for (int i = 1; i <= N; i++) { if (false == flagFinal[i]) { //如果 minDisLoc 结点加入 //可以使i 结点距离 source 变短(result[i]变小),即更新 result[i] if (result[minDisLoc] + matrix[minDisLoc][i] < result[i]) { result[i] = result[minDisLoc] + matrix[minDisLoc][i]; } } } } } } ↓ 最小生成树(Prime算法) #define N 100 int matrix[N][N]; //最小生成树信息 int treeLenthResult = 0; //最终生成的最小生成树 边的权值之和 int minDis[N]; int closeVertex[N]; void Prime(){ //设置起始结点下标是0 (从顶点0开始构造) //初始化minDis for (int i = 0; i < N; i++) { minDis[i] = matrix[i][0]; closeVertel[i] = 0; } //起始结点初始化 minDis[0] = 0; closeVertel[0] = 0; //N-1次遍历,每次都从集合N中找到一个结点,距离集合Y中所有结点值最小 for (int i = 1; i < N; i++) { int tmpDis = INF; int tmpLoc = -1; for (int j = 0; j < N; j++) { //minDis[j] != 0 --> j结点不在当前的生成树中 if ((minDis[j] != 0) && (minDis[j] < tmpDis) ) { tmpDis = minDis[j]; tmpLoc = j; } } if (tmpLoc != -1) { //tmpLoc结点 是本轮循环中找到的目标结点 //更新当前得到生成树边的权值之和 treeLenthResult += tmpDis; } //tmpLoc结点从N结合移至Y集合 minDis[tmpLoc] = 0; //更新N集合中剩余的其他结点 for (int j = 0; j < N; j++) { if (minDis[j] > matrix[j][tmpLoc]) { minDis[j] = matrix[j][tmpLoc]; closeVertex[j] = tmpLoc; //此时,j结点距离Y集合中 tmpLoc结点最近 } } } }