├── README.md
├── algorithms
├── BFS.cpp
├── Bucketsort.cpp
├── DFS.cpp
├── Dijkstra.cpp
├── Floyd.cpp
├── Huffman-code.cpp
├── KMP.cpp
├── Kruskal.cpp
├── Maximum_Subsequence_sum.cpp
├── Prim.cpp
├── ST_RMQ.cpp
├── algorithms.md
├── bubbleSort.cpp
├── heapsort.cpp
├── insertsort.cpp
├── lca1.cpp
├── lca2.cpp
├── mergesort.cpp
├── quicksort.cpp
├── shellsort.cpp
└── topsort.cpp
├── all
├── AVL_tree.cpp
├── B-tree.cpp
├── BFS.cpp
├── BinarySearchTree.cpp
├── Bucketsort.cpp
├── DFS.cpp
├── Dijkstra.cpp
├── Floyd.cpp
├── Huffman-code.cpp
├── KMP.cpp
├── Kruskal.cpp
├── Maximum_Subsequence_sum.cpp
├── Prim.cpp
├── RedBlacktree.cpp
├── Reverse_Polan.cpp
├── ST_RMQ.cpp
├── Skiplist.cpp
├── binarytree.cpp
├── bubbleSort.cpp
├── circular_list.cpp
├── double_list.cpp
├── hashtable--1.cpp
├── hashtable--2.cpp
├── heap.cpp
├── heapsort.cpp
├── insertsort.cpp
├── lca1.cpp
├── lca2.cpp
├── leftlist-heaps.cpp
├── mergesort.cpp
├── queue.cpp
├── quicksort.cpp
├── shellsort.cpp
├── skewheap.cpp
├── splay_tree.cpp
├── stack.cpp
├── topsort.cpp
├── tree.cpp
└── 数据结构与算法.md
├── graph(图).md
├── hashtable(哈希表)
├── hashtable(哈希表).md
├── hashtable--1.cpp
└── hashtable--2.cpp
├── heap(堆)
├── heap(堆).md
├── heap.cpp
├── leftlist-heaps.cpp
└── skewheap.cpp
├── images
├── image-20230530074746459.png
├── image-20230530231044041.png
├── image-20230530234156315.png
├── image-20230531114811060.png
├── image-20230702224006153.png
├── image-20230702224040084.png
├── image-20230704203814374.png
├── image-20230706002351136.png
├── image-20230706231238605.png
├── image-20230707221251382.png
├── image-20230707221904048.png
├── image-20230707222414428.png
├── image-20230707230357034.png
├── image-20230712224427132.png
├── image-20230712224654575.png
├── image-20230712224758752.png
├── image-20230713164436865.png
├── image-20230713172611705.png
├── image-20230713174303812.png
├── image-20230713175843996.png
├── image-20230714224309258.png
├── image-20230715220315995.png
├── image-20230716162205621.png
├── image-20230723144125437.png
├── image-20230723144137686.png
├── image-20230723144901708.png
├── image-20230723145117067.png
├── image-20230727192100476.png
├── image-20230808214706581.png
├── image-20230814232203982.png
├── image-20230819112844773.png
├── image-20230822185247930.png
├── image-20230831235036611.png
├── image-20230831235206080.png
├── image-20230831235326572.png
├── image-20230831235617247.png
├── image-20230917202951477.png
├── image-20230917203005664.png
├── image-20230917203147162.png
├── image-20230917203152483.png
├── image-20231112233942782.png
└── image-20231127130443086.png
├── linear list(线性表)
├── ST_RMQ.cpp
├── Skiplist.cpp
├── circular_list.cpp
├── double_list.cpp
├── linear list(线性表).md
└── list.cpp
├── queue(队列)
├── queue(队列).md
└── queue.cpp
├── stack(栈)
├── Reverse_Polan.cpp
├── stack.cpp
└── stack.md
├── tree(树)
├── AVL_tree.cpp
├── B-tree.cpp
├── BinarySearchTree.cpp
├── RedBlacktree.cpp
├── binarytree.cpp
├── splay_tree.cpp
├── tree(树).md
└── tree.cpp
└── update.py
/README.md:
--------------------------------------------------------------------------------
1 | # Data-Structure-and-Algorithms
2 | Some data structures and algorithms implemented in C++(数据结构与算法学习笔记C++版)
3 | 后期的维护我不再将其提交到github仓库里进行更新,我将会在我的博客中进行更新。
4 | 博客笔记对应地址:https://moonfordream.github.io/posts/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/
5 |
6 |
7 | # 目录
8 | - [中文版/Chinese](#chinese)
9 | - [英文版/Enlish](#en)
10 |
11 |
12 | # 中文版/Chinese
13 |
14 |
15 | ## 简介
16 | 该项目记录了一些数据结构与算法,并用C++进行了实现,用md文件进行记录笔记。
17 | 如果在md文件预览发现图片加载不出来,你可以尝试下载images文件夹中图片,然后根据我提供的update.py脚本将md文件中的url前缀更改为你下载的文件夹路径
18 |
19 | | Moonfordream| 笔记地址 |
20 | | :----:| :----: |
21 | | 总览 | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/all/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95.md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/all/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95.md) |
22 | | 算法 | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/algorithms/algorithms.md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/algorithms/algorithms.md) |
23 | | 线性表 | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/linear%20list(%E7%BA%BF%E6%80%A7%E8%A1%A8)/linear%20list(%E7%BA%BF%E6%80%A7%E8%A1%A8).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/linear%20list(%E7%BA%BF%E6%80%A7%E8%A1%A8)/linear%20list(%E7%BA%BF%E6%80%A7%E8%A1%A8).md) |
24 | | 栈 | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/stack(%E6%A0%88)/stack.md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/stack(%E6%A0%88)/stack.md) |
25 | | 队列 | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/queue(%E9%98%9F%E5%88%97)/queue(%E9%98%9F%E5%88%97).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/queue(%E9%98%9F%E5%88%97)/queue(%E9%98%9F%E5%88%97).md)|
26 | | 堆 | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/heap(%E5%A0%86)/heap(%E5%A0%86).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/heap(%E5%A0%86)/heap(%E5%A0%86).md) |
27 | | 哈希表 | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/hashtable(%E5%93%88%E5%B8%8C%E8%A1%A8)/hashtable(%E5%93%88%E5%B8%8C%E8%A1%A8).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/hashtable(%E5%93%88%E5%B8%8C%E8%A1%A8)/hashtable(%E5%93%88%E5%B8%8C%E8%A1%A8).md) |
28 | | 树 |[https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/tree(%E6%A0%91)/tree(%E6%A0%91).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/tree(%E6%A0%91)/tree(%E6%A0%91).md) |
29 | | 图 |[https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/graph(%E5%9B%BE).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/graph(%E5%9B%BE).md)|
30 |
31 |
32 |
33 |
34 | # 英文版/Enlish
35 |
36 |
37 |
38 | ## brief introduction
39 | This project records some data structures and algorithms, and implements them in C++. Notes are taken in an MD file, but the language of the notes is still Chinese. If you want to read, you can use translation software for translation or directly look at the code.
40 |
41 | If you find that the image cannot be loaded during the preview of the MD file, you can try downloading the image from the images folder, and then change the URL prefix in the MD file to the folder path you downloaded based on the update.py script I provided.
42 | | Moonfordream| Note address |
43 | | :----:| :----: |
44 | | Overview | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/all/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95.md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/all/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95.md) |
45 | | Algorithms | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/algorithms/algorithms.md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/algorithms/algorithms.md) |
46 | | Linear list | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/linear%20list(%E7%BA%BF%E6%80%A7%E8%A1%A8)/linear%20list(%E7%BA%BF%E6%80%A7%E8%A1%A8).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/linear%20list(%E7%BA%BF%E6%80%A7%E8%A1%A8)/linear%20list(%E7%BA%BF%E6%80%A7%E8%A1%A8).md) |
47 | | Stack | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/stack(%E6%A0%88)/stack.md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/stack(%E6%A0%88)/stack.md) |
48 | | Queue | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/queue(%E9%98%9F%E5%88%97)/queue(%E9%98%9F%E5%88%97).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/queue(%E9%98%9F%E5%88%97)/queue(%E9%98%9F%E5%88%97).md)|
49 | | Heap | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/heap(%E5%A0%86)/heap(%E5%A0%86).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/heap(%E5%A0%86)/heap(%E5%A0%86).md) |
50 | | Hashtable | [https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/hashtable(%E5%93%88%E5%B8%8C%E8%A1%A8)/hashtable(%E5%93%88%E5%B8%8C%E8%A1%A8).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/hashtable(%E5%93%88%E5%B8%8C%E8%A1%A8)/hashtable(%E5%93%88%E5%B8%8C%E8%A1%A8).md) |
51 | | Tree |[https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/tree(%E6%A0%91)/tree(%E6%A0%91).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/tree(%E6%A0%91)/tree(%E6%A0%91).md) |
52 | | Graph |[https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/graph(%E5%9B%BE).md](https://github.com/MoonforDream/Data-Structure-and-Algorithms/blob/main/graph(%E5%9B%BE).md)|
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/algorithms/BFS.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/algorithms/BFS.cpp
--------------------------------------------------------------------------------
/algorithms/Bucketsort.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/algorithms/Bucketsort.cpp
--------------------------------------------------------------------------------
/algorithms/DFS.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | struct listnode{
5 | int data;
6 | bool flag; //判断是否访问过
7 | int path; //存储上一个顶点
8 | int dist; //距离
9 | listnode* next;
10 | };
11 |
12 | class graph{
13 | public:
14 | graph(int n){
15 | vnum=n;
16 | an=new listnode[n+1];
17 | for(int i=0;idata=data;
28 | p->next= nullptr;
29 | p->flag=0;
30 | p->path=0;
31 | return p;
32 | };
33 | void insert(int v,int data){
34 | auto add= createNode(data);
35 | if(an[v].next== nullptr){
36 | an[v].next=add;
37 | } else{
38 | listnode* p=an[v].next;
39 | while (p->next!= nullptr){
40 | p=p->next;
41 | }
42 | p->next=add;
43 | }
44 | auto add1= createNode(v);
45 | if(an[data].next== nullptr){
46 | an[data].next=add1;
47 | } else{
48 | listnode* p=an[data].next;
49 | while (p->next!= nullptr){
50 | p=p->next;
51 | }
52 | p->next=add1;
53 | }
54 | }
55 | void DFS(int v){
56 | cout<data].flag){
61 | DFS(p->data);
62 | }
63 | p=p->next;
64 | }
65 | }
66 | private:
67 | listnode *an;
68 | int vnum;
69 | };
70 |
71 | int main() {
72 | graph g(7);
73 | g.insert(1,2);
74 | g.insert(1,4);
75 | g.insert(1,3);
76 | g.insert(2,4);
77 | g.insert(2,5);
78 | g.insert(3,6);
79 | g.insert(4,6);
80 | g.insert(4,7);
81 | g.insert(4,3);
82 | g.insert(5,4);
83 | g.insert(5,7);
84 | g.insert(7,6);
85 | g.DFS(2);
86 | system("pause");
87 | return 0;
88 | }
--------------------------------------------------------------------------------
/algorithms/Dijkstra.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/algorithms/Dijkstra.cpp
--------------------------------------------------------------------------------
/algorithms/Floyd.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/algorithms/Floyd.cpp
--------------------------------------------------------------------------------
/algorithms/Huffman-code.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 |
5 | struct tree{
6 | char data;
7 | tree* left;
8 | tree* right;
9 | int weight;
10 | };
11 |
12 | struct cmp{
13 | bool operator()(tree *a, const tree* b){
14 | return a->weightweight;
15 | }
16 | };
17 |
18 | priority_queue,cmp>pq;
19 |
20 |
21 | tree* createNode(char data,int weight){
22 | tree* p=new tree;
23 | p->data=data;
24 | p->left= nullptr;
25 | p->right= nullptr;
26 | p->weight=weight;
27 | return p;
28 | }
29 |
30 | tree* merge(tree* &t1,tree* &t2){
31 | int n=t1->weight+t2->weight;
32 | tree* p= createNode(0,n);
33 | p->left=t1;
34 | p->right=t2;
35 | return p;
36 | }
37 |
38 | tree* Huffman(){
39 | tree* p;
40 | while (!pq.empty()){
41 | tree* t1=pq.top();
42 | pq.pop();
43 | tree* t2=pq.top();
44 | pq.pop();
45 | p=merge(t1,t2);
46 | pq.push(p);
47 | }
48 | return p;
49 | }
50 |
51 | int main() {
52 | for(int i=0;i<10;i++){
53 | char data=char('a'+i);
54 | tree* p= createNode(data,i+5);
55 | pq.push(p);
56 | }
57 | tree* p=Huffman();
58 | system("pause");
59 | return 0;
60 | }
61 |
--------------------------------------------------------------------------------
/algorithms/KMP.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 |
5 | void getnext(int *next,const string& s,int size){
6 | //初始化
7 | int j=0;
8 | next[0]=0;
9 | for(int i=1;i0&&s[i]!=s[j]){
12 | j=next[j-1]; //回溯找到相等位置或者回到0
13 | }
14 | //前后缀相同情况
15 | if(s[i]==s[j]) j++;
16 | next[i]=j;
17 | }
18 | }
19 |
20 |
21 | int KMP(const string &text,const string &mode){
22 | int len=text.size();
23 | if(len==0) return 0;
24 | int size=mode.size();
25 | int j=0,next[size];
26 | getnext(next,mode,size);
27 | for(int i=0;i0&&text[i]!=mode[j]){
29 | j=next[j-1];
30 | }
31 | if(text[i]==mode[j]) j++;
32 | if(j==size) return (i-j+1);
33 | }
34 | return -1;
35 | }
36 |
37 |
38 | int main() {
39 | string text="mississippi"; //文本串
40 | string mode="issip"; //模式串
41 | cout<
2 | #include
3 | using namespace std;
4 | //例子
5 | const int N=1e6+10;
6 | int f[N][20]; //20是由log2(n+1)+1算出来的
7 | int n,m;
8 |
9 | int query(int l,int r){
10 | // int x=(int)log(r-l+1)/log(2);
11 | int x=(int)log2(r-l+1);
12 | return max(f[l][x],f[r-(1<>n>>m;
18 | for(int i=1;i<=n;++i){
19 | int p;
20 | cin>>p;
21 | f[i][0]=p;
22 | }
23 | //外层循环是遍历列,列不需要遍历到n,而是2的j次方小于等于n
24 | // 因为f[i][j]代表的是从i开始的2的j次方个元素的最值,因此j最大只能取到log2(n)
25 | for(int j=1;(1<>x>>y;
34 | cout<
2 | using namespace std;
3 |
4 | //冒泡排序
5 | //冒泡排序时间复杂度O(n²)
6 | void bubbleSort(int an[],int len){
7 | for(int i=0;ian[j+1]){
10 | int temp=an[j+1];
11 | an[j+1]=an[j];
12 | an[j]=temp;
13 | }
14 | }
15 | }
16 | }
17 |
18 |
19 | int main() {
20 | int an[]={3,7,10,-1,20,10,55,70,80,90};
21 | int len=sizeof(an)/sizeof(an[0]); //求数组元素个数
22 | bubbleSort(an,len);
23 | for(int i=0;i
2 | using namespace std;
3 | #define leftchild(i) (2*(i)+1) //定义宏函数,找到根节点的左孩子
4 |
5 | //构建堆
6 | void buildheap(int* an,int len,int index){
7 | int temp,child;
8 | for(temp=an[index];leftchild(index)an[child]){
11 | child++;
12 | }
13 | if(an[child]>temp){
14 | an[index]=an[child];
15 | }else{
16 | break;
17 | }
18 | }
19 | an[index]=temp;
20 | }
21 |
22 | //堆排序
23 | void heapsort(int* an,int len){
24 | for(int i=(len-1)/2;i>=0;i--){
25 | buildheap(an,len,i);
26 | }
27 | for(int i=len-1;i>0;i--){
28 | int temp=an[0];
29 | an[0]=an[i];
30 | an[i]=temp;
31 | buildheap(an,i,0);
32 | }
33 | }
34 |
35 | int main() {
36 | int an[]={7,8,9,10,1,-2,53,26,77,23,1034,-6};
37 | int len=sizeof(an)/sizeof(an[0]);
38 | heapsort(an,len);
39 | for(int i=0;i
2 | using namespace std;
3 |
4 | //插入排序
5 | void insertsort(int *an,int len){
6 | for(int i=1;i<=len-1;i++){
7 | int temp=an[i];
8 | int j;
9 | for(j=i;j>0&&an[j-1]>temp;j--){
10 | an[j]=an[j-1];
11 | }
12 | an[j]=temp;
13 | }
14 | }
15 |
16 | int main() {
17 | int an[]={7,8,9,10,1,-2,53,26,77,23,1034,-6};
18 | int len=sizeof(an)/sizeof(an[0]);
19 | insertsort(an,len);
20 | for(int i=0;i
2 | using namespace std;
3 |
4 | const int N=5e5+20;
5 | int n,m,s,a,b; //n为节点数,m为查询次数,s为根节点编号,a和b用于临时存储节点的临时变量
6 | int dep[N],p[N];
7 | vectorg[N]; //存储边集
8 |
9 | void dfs(int u,int d){
10 | dep[u]=d;
11 | int size=g[u].size();
12 | for(int i=0;idep[y]) x=p[x];
23 | while(x!=y){
24 | x=p[x];
25 | y=p[y];
26 | }
27 | return x;
28 | }
29 |
30 |
31 | int main() {
32 | cin>>n>>m>>s;
33 | for(int i=1;i>a>>b;
35 | g[a].emplace_back(b);
36 | g[b].emplace_back(a);
37 | }
38 | dfs(s,0);
39 | while(m--){
40 | cin>>a>>b;
41 | cout<
2 | using namespace std;
3 |
4 | const int N=5e5+20;
5 | int n,m,s,a,b; //n为节点数,m为查询次数,s为根节点编号,a和b用于临时存储节点的临时变量
6 | int dep[N],f[N][22]; //log2(N)算出来19,可以创建大于19的数组
7 | vectorg[N]; //存储边集
8 |
9 | void dfs(int u,int p,int d){
10 | dep[u]=d;
11 | f[u][0]=p;
12 | for(int i=1;i<=log2(dep[u]);++i){
13 | f[u][i]=f[f[u][i-1]][i-1];
14 | }
15 | int size=g[u].size();
16 | for(int i=0;i=0;--i){
28 | if((1<=0;--i){
32 | if(f[x][i]!=f[y][i]){
33 | x=f[x][i];
34 | y=f[y][i];
35 | }
36 | }
37 | return f[x][0];
38 | }
39 |
40 |
41 | int main() {
42 | cin>>n>>m>>s;
43 | for(int i=1;i>a>>b;
45 | g[a].emplace_back(b);
46 | g[b].emplace_back(a);
47 | }
48 | dfs(s,s,0);
49 | while(m--){
50 | cin>>a>>b;
51 | cout<
2 | using namespace std;
3 |
4 |
5 | //合并操作
6 | void merge(int*an,int *temarr,int lpos,int rpos,int rightend){
7 | int leftend=rpos-1;
8 | int nums=(rightend-lpos)+1;
9 | int tempos=lpos;
10 | //进行比较lpos和rpos位上的元素
11 | while (lpos<=leftend&&rpos<=rightend){
12 | if(an[lpos]
2 | using namespace std;
3 |
4 | //希尔排序
5 | void shellsort(int *an,int len){
6 | for(int i=(len-1)/2;i>0;i/=2){
7 | //插入排序
8 | for(int j=i;j=i&&temp=len;k++);
35 | for(int d=Sedgewick[k];d>0;d=Sedgewick[++k]){
36 | for(int i=d;i=d&&an[j-d]>temp;j-=d){
40 | an[j]=an[j-d];
41 | }
42 | an[j]=temp;
43 | }
44 | }
45 | }
46 |
47 | int main() {
48 | int an[]={7,8,9,10,1,-2,53,26,77,23,1034,-6};
49 | int len=sizeof(an)/sizeof(an[0]);
50 | // shellsort(an,len);
51 | shellsort_pro(an,len);
52 | for(int i=0;i
2 | #include
3 | using namespace std;
4 |
5 | struct listnode{
6 | int data;
7 | listnode* next;
8 | };
9 |
10 | class graph{
11 | public:
12 | graph(int n){
13 | vnum=n;
14 | an=new listnode[n+1];
15 | indegree=(int*) malloc(sizeof(int)*(n+1));
16 | for(int i=0;idata=data;
25 | p->next= nullptr;
26 | return p;
27 | };
28 | void insert(int v,int data){
29 | auto add= createNode(data);
30 | if(an[v].next== nullptr){
31 | an[v].next=add;
32 | } else{
33 | listnode* p=an[v].next;
34 | while (p->next!= nullptr){
35 | p=p->next;
36 | }
37 | p->next=add;
38 | }
39 | indegree[data]++;
40 | }
41 | int findedgenull(){
42 | for(int i=1;i<=vnum;i++){
43 | if(indegree[i]==0){
44 | return i;
45 | }
46 | }
47 | return 0;
48 | }
49 | //拓扑排序
50 | void topsort(){
51 | queueq;
52 | int v=findedgenull();
53 | if(v==0){
54 | cout<<"该图含有圈"<data]==0){
69 | q.push(p->data);
70 | }
71 | p=p->next;
72 | }
73 | }
74 | cout<
2 |
3 | using namespace std;
4 |
5 | //平衡查找树是其每个节点的左子树和右子树的高度最多差1的二叉查找树
6 | struct AVL{
7 | int data;
8 | AVL* left;
9 | AVL* right;
10 | int height; //节点高度
11 | };
12 |
13 | AVL* createNode(int data){
14 | auto p=new AVL;
15 | p->data=data;
16 | p->right= nullptr;
17 | p->left= nullptr;
18 | p->height=0;
19 | return p;
20 | }
21 |
22 | //防止出现空的高度
23 | int Height(AVL* root){
24 | if(root== nullptr){
25 | return -1;
26 | }else{
27 | return root->height;
28 | }
29 | }
30 |
31 | //左左情况单旋转函数
32 | AVL* SingleRotatewithLeft(AVL* &k1){
33 | AVL* k2;
34 | k2=k1->left;
35 | k1->left=k2->right;
36 | k2->right=k1;
37 | k1->height= max(Height(k1->left), Height(k1->right))+1;
38 | k2->height= max(Height(k2->left), Height(k2->right))+1;
39 | return k2;
40 | }
41 |
42 | //右右情况单旋转函数
43 | AVL* SingleRotatewithRight(AVL* &k1){
44 | AVL* k2;
45 | k2=k1->right;
46 | k1->right=k2->left;
47 | k2->left=k1;
48 | k1->height= max(Height(k1->left), Height(k1->right))+1;
49 | k2->height= max(Height(k2->left), Height(k2->right))+1;
50 | return k2;
51 | }
52 |
53 | //左右情况双旋转
54 | AVL* DoubleRotatewithLeft(AVL* &k1){
55 | //非递归形式
56 | // AVL* k2;
57 | // AVL* k3;
58 | // k2=k1->left;
59 | // k3=k1->left->right;
60 | // k1->left=k3->right;
61 | // k2->right=k3->left;
62 | // k3->left=k2;
63 | // k3->right=k1;
64 | // k1->height=max(Height(k1->left), Height(k1->right))+1;
65 | // k2->height=max(Height(k2->left), Height(k2->right))+1;
66 | // k3->height=max(Height(k3->left), Height(k3->right))+1;
67 | // return k3;
68 | //递归形式,建议用递归,好记
69 | k1->left= SingleRotatewithRight(k1->left); //k2跟k3单旋转
70 | return SingleRotatewithLeft(k1); //k1跟现在的k2(原来的k3)单旋转
71 | }
72 |
73 | //右左情况双旋转
74 | AVL* DoubleRotatewithRight(AVL* &k1){
75 | //非递归形式
76 | // AVL* k2;
77 | // AVL* k3;
78 | // k2=k1->right;
79 | // k3=k1->right->left;
80 | // k1->right=k3->left;
81 | // k2->left=k3->right;
82 | // k3->left=k1;
83 | // k3->right=k2;
84 | // k1->height=max(Height(k1->left), Height(k1->right))+1;
85 | // k2->height=max(Height(k2->left), Height(k2->right))+1;
86 | // k3->height=max(Height(k3->left), Height(k3->right))+1;
87 | // return k3;
88 | //递归形式
89 | k1->right= SingleRotatewithLeft(k1->right); //k2跟k3单旋转
90 | return SingleRotatewithRight(k1); //k1跟现在的k2(原来的k3)单旋转
91 | }
92 |
93 |
94 | //插入
95 | AVL* insert(AVL* &root,int data){
96 | if(NULL==root){
97 | AVL* add= createNode(data);
98 | root=add;
99 | }else if(datadata){
100 | root->left= insert(root->left,data);
101 | //判断高度差
102 | if(2== Height(root->left)- Height(root->right)){
103 | //左左情况,情形1,单旋转
104 | if(dataleft->data){
105 | root=SingleRotatewithLeft(root);
106 | }else{ //左右情况,情形2,双旋转
107 | root=DoubleRotatewithLeft(root);
108 | }
109 | }
110 | }else if(data>root->data){
111 | root->right= insert(root->right,data);
112 | if(2== Height(root->right)- Height(root->left)){
113 | //右右情况,情形4,单旋转
114 | if(data>root->right->data){
115 | root=SingleRotatewithRight(root);
116 | }else{ //右左情况,情形3,双旋转
117 | root=DoubleRotatewithRight(root);
118 | }
119 | }
120 | }
121 | //通过递归,从后序开始往上回,这样就能保证树的高度的正确性,这样子到了根节点就拿到了最大的高度
122 | root->height= max(Height(root->left), Height(root->right))+1;
123 | return root;
124 | }
125 |
126 |
127 | //查找
128 | AVL* Search(AVL* root,int data){
129 | if(NULL==root){
130 | return NULL;
131 | }
132 | if(datadata){
133 | root->left= Search(root->left,data);
134 | }else if(data>root->data){
135 | root->right= Search(root->right,data);
136 | }else
137 | return root;
138 | }
139 |
140 |
141 | //查找最小值
142 | int findmin(AVL* root){
143 | //递归形式
144 | if(NULL==root){
145 | return root->data;
146 | }
147 | if(root->left!=NULL){
148 | return findmin(root->left);
149 | }else{
150 | return root->data;
151 | }
152 |
153 | //非递归形式
154 | // if(NULL!=root){
155 | // while (root->left!=NULL){
156 | // root=root->left;
157 | // }
158 | // return root->data
159 | // }
160 | // return NULL;
161 | }
162 |
163 | //查找最大值
164 | int findmax(AVL* root){
165 | //递归形式
166 | // if(NULL==root){
167 | // return NULL;
168 | // }
169 | // if(NULL!=root->right){
170 | // return findmax(root->right);
171 | // }else{
172 | // return root->data;
173 | // }
174 |
175 | //非递归形式
176 | if(NULL!=root){
177 | while (root->right!=NULL){
178 | root=root->right;
179 | }
180 | }
181 | return root->data;
182 | }
183 |
184 |
185 | //删除节点,删除操作也会导致AVL树平衡破坏,所以删除操作也需要对AVL树做判断
186 | AVL* del(AVL* &root,int data){
187 | if(NULL==root){
188 | return NULL;
189 | }else if(datadata){
190 | root->left= del(root->left,data);
191 | if(2== Height(root->left)- Height(root->right)){
192 | if(dataleft->data){
193 | root= SingleRotatewithLeft(root);
194 | }else{
195 | root= DoubleRotatewithLeft(root);
196 | }
197 | }
198 | }else if(data>root->data){
199 | root->right=del(root->right,data);
200 | if(2== Height(root->right)- Height(root->left)){
201 | if(data>root->right->data){
202 | root= SingleRotatewithRight(root);
203 | }else{
204 | root= DoubleRotatewithRight(root);
205 | }
206 | }
207 | }else if(root->left&&root->right){
208 | int temp= findmin(root);
209 | root->data=temp;
210 | root->right=del(root->right,temp);
211 | }else{
212 | AVL* p=root;
213 | if(NULL==root->left){
214 | root=root->right;
215 | }else if(NULL==root->right){
216 | root=root->left;
217 | }
218 | delete p;
219 | }
220 | if(root!=NULL)
221 | root->height=max(Height(root->left), Height(root->right))+1;
222 | return root;
223 | }
224 |
225 |
226 | //清空树
227 | void destroy(AVL* &root){
228 | if(NULL==root){
229 | return;
230 | }
231 | destroy(root->left);
232 | destroy(root->right);
233 | delete root;
234 | }
235 |
236 | //打印,中序遍历
237 | void inorderprint(AVL* root){
238 | if(NULL==root){
239 | return;
240 | }
241 | inorderprint(root->left);
242 | cout<data<<" ";
243 | inorderprint(root->right);
244 | }
245 |
246 | int main() {
247 | AVL* root=NULL;
248 | insert(root,4);
249 | insert(root,3);
250 | insert(root,7);
251 | insert(root,8);
252 | insert(root,6);
253 | insert(root,5);
254 | // del(root,5);
255 | // destroy(root);
256 | inorderprint(root);
257 | system("pause");
258 | return 0;
259 | }
260 |
--------------------------------------------------------------------------------
/all/B-tree.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 |
5 | struct btree{
6 | int level; //树的阶数
7 | vectorkeys; //关键字数组
8 | vectorchild; //子节点数组
9 | int keynum; //节点的关键字数目
10 | btree* parent; //子节点的父节点
11 | };
12 |
13 | btree* createNode(int level){
14 | auto p=new btree;
15 | p->level=level;
16 | p->keynum=0;
17 | p->parent= nullptr;
18 | for(int i=0;i<=p->level;i++){
19 | p->child.push_back(nullptr);
20 | p->keys.push_back(0);
21 | }
22 | return p;
23 | }
24 |
25 | pair find(btree* root,int key){
26 | int i;
27 | for(i=root->keynum;i>0;i--){
28 | if(keykeys[i]){
29 | continue;
30 | }else if(key>root->keys[i]){
31 | break;
32 | }else{
33 | return make_pair(root,i);
34 | }
35 | }
36 | pairp=find(root->child[i],key);
37 | return p;
38 | }
39 |
40 |
41 | void splitNode(btree* &root,btree* p,int index){
42 | if(p != nullptr && p->keynum == p->level) {
43 | //分裂节点
44 | int mid=p->keynum/2+p->keynum%2;
45 | btree* newnode= createNode(p->level);
46 | newnode->parent=p->parent;
47 | for(int j=root->keynum;j>index-1;j--){
48 | root->keys[j+1]=root->keys[j];
49 | }
50 | root->keys[index]=p->keys[mid];
51 | root->keynum++;
52 | for(int j=mid+1;j<=p->keynum;j++){
53 | newnode->keys[j-mid]=p->keys[j];
54 | newnode->keynum++;
55 | }
56 | p->keynum=p->keynum-newnode->keynum-1;
57 | int k;
58 | for(k=root->level-1;k>index-1;k--){
59 | root->child[k+1]=root->child[k];
60 | }
61 | k++;
62 | root->child[k]=newnode;
63 | }
64 | if(root->keynum==root->level) {
65 | btree *newchild = createNode(root->level);
66 | int mid = root->keynum / 2 + root->keynum % 2;
67 | for (int i = mid + 1; i <= root->level; i++) {
68 | newchild->keys[i - mid] = root->keys[i];
69 | newchild->keynum++;
70 | }
71 | for (int j = newchild->keynum; j <= newchild->level; j++) {
72 | if(root->child[j])
73 | root->child[j]->parent=newchild;
74 | newchild->child[j - newchild->keynum] = root->child[j];
75 | root->child[j] = nullptr;
76 | }
77 | if (root->parent == nullptr) {
78 | btree *newnode = createNode(root->level);
79 | newnode->keys[1] = root->keys[mid];
80 | newnode->keynum++;
81 | root->keynum = root->level - newchild->keynum - 1;
82 | newnode->child[0] = root;
83 | newnode->child[1] = newchild;
84 | root->parent = newnode;
85 | newchild->parent = newnode;
86 | root = newnode;
87 | } else {
88 | newchild->parent = root->parent;
89 | root->keynum = root->level - newchild->keynum - 1;
90 | int a = root->parent->keynum;
91 | while (a > 0 && root->keys[mid] < root->parent->keys[a]) {
92 | root->parent->keys[a + 1] = root->parent->keys[a];
93 | root->parent->child[a + 1] = root->parent->child[a];
94 | a--;
95 | }
96 | a++;
97 | root->parent->keys[a] = root->keys[mid];
98 | root->parent->keynum++;
99 | root->parent->child[a] = newchild;
100 | }
101 | }
102 | }
103 |
104 | btree* insert(btree* &root,int key){
105 | if(0==root->keynum){
106 | root->keys[1]=key;
107 | root->keynum++;
108 | return root;
109 | }
110 | int index=root->keynum;
111 | while (index>0&&keykeys[index]){
112 | root->keys[index+1]=root->keys[index];
113 | index--;
114 | }
115 | index++;
116 | if(root->child[0]!=nullptr){
117 | btree* p;
118 | if(index==root->keynum){
119 | p=root->child[index+1];
120 | }else{
121 | p=root->child[index-1];
122 | }
123 | if(root->child[0]->child[0]!=nullptr){
124 | p= insert(p,key);
125 | }else if(root->child[0]->child[0]==nullptr){
126 | int i=p->keynum;
127 | while (i>0&&keykeys[i]){
128 | p->keys[i+1]=p->keys[i];
129 | i--;
130 | }
131 | i++;
132 | p->keys[i]=key;
133 | p->keynum++;
134 | }
135 | splitNode(root,p,index);
136 | }else{
137 | root->keys[index]=key;
138 | root->keynum++;
139 | splitNode(root, nullptr,-1);
140 | }
141 | return root;
142 | }
143 |
144 | int findmax(btree* root){
145 | if(nullptr==root){
146 | return 0;
147 | }else if(root->child[0]!= nullptr){
148 | return findmax(root->child[root->keynum]);
149 | }
150 | return root->keys[root->keynum];
151 | }
152 |
153 |
154 | void merge(btree* &root,int key,int min,int n){
155 | int n1 = root->child[n-1]->keynum;
156 | int n2 = root->child[n]->keynum;
157 | if (n1 > min) {
158 | for (int j = n2; j > 0; j--) {
159 | root->child[n]->keys[j + 1] = root->child[n]->keys[j];
160 | root->child[n]->child[j + 1] = root->child[n]->child[j];
161 | }
162 | root->child[n]->child[1] = root->child[n]->child[0];
163 | root->child[n]->keys[1] = root->keys[n];
164 | root->keys[n]=root->child[n-1]->keys[n1];
165 | root->child[n]->child[0] = root->child[n-1]->child[n1];
166 | root->child[n-1]->child[n1] = nullptr;
167 | root->child[n-1]->child[0]->parent = root->child[n-1];
168 | root->child[n-1]->keynum--;
169 | root->child[n-1]->keys[n1] = NULL;
170 | root->child[n]->keynum++;
171 | } else if (n2 > min) {
172 | root->child[n-1]->keys[n1+1]=root->keys[n];
173 | root->keys[n]=root->child[n]->keys[1];
174 | root->child[n-1]->child[n1 + 1] = root->child[n]->child[0];
175 | root->child[n-1]->child[n1 + 1]->parent = root->child[n-1];
176 | root->child[n-1]->keynum++;
177 | for (int j = 1; j < n2; j++) {
178 | root->child[n]->keys[j] = root->child[n]->keys[j + 1];
179 | root->child[n]->child[j - 1] = root->child[n]->child[j];
180 | }
181 | root->child[n]->child[n2-1]=root->child[n]->child[n2];
182 | root->child[n]->keys[n2] = NULL;
183 | root->child[n]->child[n2] = nullptr;
184 | root->child[n]->keynum--;
185 | } else {
186 | root->child[n-1]->keys[n1+1]=root->keys[n];
187 | root->child[n-1]->keynum++;
188 | int n3 = n2 + n1+1;
189 | for (int j = n1 + 2; j <= n3; j++) {
190 | root->child[n-1]->keys[j] = root->child[n]->keys[j - n1-1];
191 | root->child[n-1]->child[j-1]=root->child[n]->child[j];
192 | root->child[n-1]->keynum++;
193 | }
194 | root->child[n]=nullptr;
195 | int index = root->keynum;
196 | while (index > n && key < root->keys[index]) {
197 | root->keys[index-1]=root->keys[index];
198 | root->child[index-1]=root->child[index];
199 | index--;
200 | }
201 | root->child[root->keynum]= nullptr;
202 | root->keynum--;
203 | if(root->parent== nullptr&&root->keynum==0){
204 | root->child[0]->parent= nullptr;
205 | root=root->child[0];
206 | }
207 | }
208 | }
209 |
210 | void del(btree* &root,int key){
211 | if(nullptr==root){
212 | return;
213 | }else{
214 | int i;
215 | for(i=root->keynum;i>0;i--){
216 | if(keykeys[i]){
217 | continue;
218 | }else if(key>root->keys[i]){
219 | del(root->child[i],key);
220 | }else{
221 | break;
222 | }
223 | }
224 | int min=(root->level/2+root->level%2)-1;
225 | if(0==i){
226 | if(root->child[i]&&root->child[i+1]){
227 | if(root->child[i]->keynum>=min&&root->child[i+1]->keynum>=min){
228 | del(root->child[i],key);
229 | }
230 | }
231 | i++;
232 | }
233 | if(root->child[0]!= nullptr){
234 | if(root->keynum>=min){
235 | if(root->keys[i]==key){
236 | int temp= findmax(root->child[i-1]);
237 | root->keys[i]=temp;
238 | del(root->child[i-1],temp);
239 | merge(root,key,min,i);
240 | }else if(keykeys[i]){
241 | if(root->child[i-1]->keynumchild[i]->keynumkeynum;j++){
255 | if(root->keys[j]==key){
256 | break;
257 | }
258 | }
259 | for(int d=j;dkeynum;d++){
260 | root->keys[d]=root->keys[d+1];
261 | }
262 | root->keys[root->keynum]=NULL;
263 | if(root->keynum>min){
264 | root->keynum--;
265 | }else{
266 | root->keynum--;
267 | int index=root->parent->keynum;
268 | for(int k=root->keynum;k>0;k--){
269 | root->keys[k+1]=root->keys[k];
270 | }
271 | while (index>0&&key<=root->parent->keys[index]){
272 | index--;
273 | }
274 | if(0==index){
275 | root->keys[root->keynum+1]=root->parent->keys[1];
276 | }else{
277 | root->keys[root->keynum+1]=root->parent->keys[index];
278 | }
279 | }
280 | }
281 | }
282 | }
283 |
284 | //中序遍历
285 | void inorderprint(btree* root){
286 | if(nullptr!=root){
287 | int i;
288 | for(i=0;ikeynum;i++){
289 | if(root->child[i]!= nullptr){
290 | inorderprint(root->child[i]);
291 | }
292 | cout<keys[i+1]<<" ";
293 | }
294 | if(root->child[i]!= nullptr)
295 | inorderprint(root->child[i]);
296 | }
297 | }
298 |
299 |
300 | int main(){
301 | btree* root= createNode(4);
302 | insert(root,1);
303 | insert(root,2);
304 | insert(root,3);
305 | insert(root,4);
306 | insert(root,10);
307 | insert(root,15);
308 | insert(root,23);
309 | insert(root,28);
310 | insert(root,30);
311 | insert(root,31);
312 | insert(root,32);
313 | insert(root,33);
314 | insert(root,34);
315 | insert(root,35);
316 | insert(root,36);
317 | insert(root,37);
318 | insert(root,38);
319 | insert(root,39);
320 | insert(root,40);
321 | insert(root,41);
322 | insert(root,42);
323 | insert(root,43);
324 | insert(root,44);
325 | del(root,31);
326 | inorderprint(root);
327 | system("pause");
328 | return 0;
329 | }
330 |
331 |
--------------------------------------------------------------------------------
/all/BFS.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/all/BFS.cpp
--------------------------------------------------------------------------------
/all/BinarySearchTree.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/all/BinarySearchTree.cpp
--------------------------------------------------------------------------------
/all/Bucketsort.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/all/Bucketsort.cpp
--------------------------------------------------------------------------------
/all/DFS.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | struct listnode{
5 | int data;
6 | bool flag; //判断是否访问过
7 | int path; //存储上一个顶点
8 | int dist; //距离
9 | listnode* next;
10 | };
11 |
12 | class graph{
13 | public:
14 | graph(int n){
15 | vnum=n;
16 | an=new listnode[n+1];
17 | for(int i=0;idata=data;
28 | p->next= nullptr;
29 | p->flag=0;
30 | p->path=0;
31 | return p;
32 | };
33 | void insert(int v,int data){
34 | auto add= createNode(data);
35 | if(an[v].next== nullptr){
36 | an[v].next=add;
37 | } else{
38 | listnode* p=an[v].next;
39 | while (p->next!= nullptr){
40 | p=p->next;
41 | }
42 | p->next=add;
43 | }
44 | auto add1= createNode(v);
45 | if(an[data].next== nullptr){
46 | an[data].next=add1;
47 | } else{
48 | listnode* p=an[data].next;
49 | while (p->next!= nullptr){
50 | p=p->next;
51 | }
52 | p->next=add1;
53 | }
54 | }
55 | void DFS(int v){
56 | cout<data].flag){
61 | DFS(p->data);
62 | }
63 | p=p->next;
64 | }
65 | }
66 | private:
67 | listnode *an;
68 | int vnum;
69 | };
70 |
71 | int main() {
72 | graph g(7);
73 | g.insert(1,2);
74 | g.insert(1,4);
75 | g.insert(1,3);
76 | g.insert(2,4);
77 | g.insert(2,5);
78 | g.insert(3,6);
79 | g.insert(4,6);
80 | g.insert(4,7);
81 | g.insert(4,3);
82 | g.insert(5,4);
83 | g.insert(5,7);
84 | g.insert(7,6);
85 | g.DFS(2);
86 | system("pause");
87 | return 0;
88 | }
--------------------------------------------------------------------------------
/all/Dijkstra.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/all/Dijkstra.cpp
--------------------------------------------------------------------------------
/all/Floyd.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/all/Floyd.cpp
--------------------------------------------------------------------------------
/all/Huffman-code.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 |
5 | struct tree{
6 | char data;
7 | tree* left;
8 | tree* right;
9 | int weight;
10 | };
11 |
12 | struct cmp{
13 | bool operator()(tree *a, const tree* b){
14 | return a->weightweight;
15 | }
16 | };
17 |
18 | priority_queue,cmp>pq;
19 |
20 |
21 | tree* createNode(char data,int weight){
22 | tree* p=new tree;
23 | p->data=data;
24 | p->left= nullptr;
25 | p->right= nullptr;
26 | p->weight=weight;
27 | return p;
28 | }
29 |
30 | tree* merge(tree* &t1,tree* &t2){
31 | int n=t1->weight+t2->weight;
32 | tree* p= createNode(0,n);
33 | p->left=t1;
34 | p->right=t2;
35 | return p;
36 | }
37 |
38 | tree* Huffman(){
39 | tree* p;
40 | while (!pq.empty()){
41 | tree* t1=pq.top();
42 | pq.pop();
43 | tree* t2=pq.top();
44 | pq.pop();
45 | p=merge(t1,t2);
46 | pq.push(p);
47 | }
48 | return p;
49 | }
50 |
51 | int main() {
52 | for(int i=0;i<10;i++){
53 | char data=char('a'+i);
54 | tree* p= createNode(data,i+5);
55 | pq.push(p);
56 | }
57 | tree* p=Huffman();
58 | system("pause");
59 | return 0;
60 | }
61 |
--------------------------------------------------------------------------------
/all/KMP.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 |
5 | void getnext(int *next,const string& s,int size){
6 | //初始化
7 | int j=0;
8 | next[0]=0;
9 | for(int i=1;i0&&s[i]!=s[j]){
12 | j=next[j-1]; //回溯找到相等位置或者回到0
13 | }
14 | //前后缀相同情况
15 | if(s[i]==s[j]) j++;
16 | next[i]=j;
17 | }
18 | }
19 |
20 |
21 | int KMP(const string &text,const string &mode){
22 | int len=text.size();
23 | if(len==0) return 0;
24 | int size=mode.size();
25 | int j=0,next[size];
26 | getnext(next,mode,size);
27 | for(int i=0;i0&&text[i]!=mode[j]){
29 | j=next[j-1];
30 | }
31 | if(text[i]==mode[j]) j++;
32 | if(j==size) return (i-j+1);
33 | }
34 | return -1;
35 | }
36 |
37 |
38 | int main() {
39 | string text="mississippi"; //文本串
40 | string mode="issip"; //模式串
41 | cout<
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | bool flag(char a,char b){
8 | int a1,b1;
9 | if(a=='+'||a=='-'){
10 | a1=1;
11 | }else if(a=='*'||a=='/'){
12 | a1=2;
13 | }else if(a=='('||a==')'){
14 | a1=3;
15 | }
16 | if(b=='+'||b=='-'){
17 | b1=1;
18 | }else if(b=='*'||b=='/'){
19 | b1=2;
20 | }else if(b=='('||b==')'){
21 | b1=3;
22 | }
23 | return a1>=b1;
24 | }
25 |
26 | vector reversePolan(char *an,int len){
27 | stacks;
28 | vectorv;
29 | int cnt=0;
30 | for(int i=0;i
2 | #include
3 | using namespace std;
4 | //例子
5 | const int N=1e6+10;
6 | int f[N][20]; //20是由log2(n+1)+1算出来的
7 | int n,m;
8 |
9 | int query(int l,int r){
10 | // int x=(int)log(r-l+1)/log(2);
11 | int x=(int)log2(r-l+1);
12 | return max(f[l][x],f[r-(1<>n>>m;
18 | for(int i=1;i<=n;++i){
19 | int p;
20 | cin>>p;
21 | f[i][0]=p;
22 | }
23 | //外层循环是遍历列,列不需要遍历到n,而是2的j次方小于等于n
24 | // 因为f[i][j]代表的是从i开始的2的j次方个元素的最值,因此j最大只能取到log2(n)
25 | for(int j=1;(1<>x>>y;
34 | cout<
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | struct Node{
7 | int val; //存储元素值
8 | vectornext; //存储各层数指针的数组
9 | int level; //阶数
10 | };
11 |
12 |
13 | class skiplist{
14 | public:
15 | skiplist(int level):Maxlevel(level){
16 | head= createNode(NULL,Maxlevel);
17 | }
18 | ~skiplist() {
19 | Node* tail=head;
20 | Node* p;
21 | while (tail!= nullptr){
22 | p=tail;
23 | tail=tail->next[0];
24 | delete p;
25 | }
26 | head= nullptr;
27 | };
28 |
29 | Node* find(int data);
30 | void insert(int data);
31 | void del(int data);
32 | void print();
33 |
34 | private:
35 | Node* head;
36 | int Maxlevel;
37 |
38 | Node* createNode(int data,int level){
39 | auto p = new Node;
40 | p->val=data;
41 | p->level=level;
42 | p->next.resize(level,NULL);
43 | return p;
44 | }
45 |
46 | int rand_level(){
47 | int level=1;
48 | while(rand()%2&&level<=Maxlevel){
49 | level++;
50 | }
51 | return level;
52 | }
53 |
54 |
55 | };
56 |
57 | Node *skiplist::find(int data) {
58 | Node* p=head;
59 | for(int i=Maxlevel-1;i>=0;i--){
60 | while (p->next[i]!= nullptr&&p->next[i]->valnext[i];
62 | }
63 | }
64 | if(p->next[0]!= nullptr&&p->next[0]->val==data){
65 | return p->next[0];
66 | }
67 | return nullptr;
68 | }
69 |
70 | void skiplist::insert(int data) {
71 | int level=rand_level();
72 | Node* add= createNode(data,level);
73 | if(head->next[0]== nullptr){
74 | head->next[0]=add;
75 | return;
76 | }
77 | Node* p=head;
78 | Node* prev[level];
79 | for(int i=level-1;i>=0;i--){
80 | while (p->next[i]!= nullptr&&p->next[i]->valnext[i];
82 | }
83 | prev[i]=p;
84 | }
85 | for(int i=0;inext[i]=prev[i]->next[i];
87 | prev[i]->next[i]=add;
88 | }
89 | }
90 |
91 | void skiplist::del(int data) {
92 | Node* p=head;
93 | Node* prev[Maxlevel];
94 | for(int i=Maxlevel-1;i>=0;i--){
95 | while (nullptr!=p->next[i]&&p->next[i]->valnext[i];
97 | }
98 | prev[i]=p;
99 | }
100 | if(p->next[0]!= nullptr&&p->next[0]->val==data){
101 | Node* tail=p->next[0];
102 | for(int i=Maxlevel-1;i>=0;i--){
103 | if(prev[i]->next[i]!= nullptr&&prev[i]->next[i]->val==data)
104 | prev[i]->next[i]=prev[i]->next[i]->next[i];
105 | }
106 | delete tail;
107 | }
108 | }
109 |
110 | void skiplist::print() {
111 | Node* p=head->next[0];
112 | while (p!= nullptr){
113 | cout<val<<" ";
114 | p=p->next[0];
115 | }
116 | cout<val;
130 | sl.print();
131 | system("pause");
132 | return 0;
133 | }
134 |
--------------------------------------------------------------------------------
/all/binarytree.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/all/binarytree.cpp
--------------------------------------------------------------------------------
/all/bubbleSort.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | //冒泡排序
5 | //冒泡排序时间复杂度O(n²)
6 | void bubbleSort(int an[],int len){
7 | for(int i=0;ian[j+1]){
10 | int temp=an[j+1];
11 | an[j+1]=an[j];
12 | an[j]=temp;
13 | }
14 | }
15 | }
16 | }
17 |
18 |
19 | int main() {
20 | int an[]={3,7,10,-1,20,10,55,70,80,90};
21 | int len=sizeof(an)/sizeof(an[0]); //求数组元素个数
22 | bubbleSort(an,len);
23 | for(int i=0;i
2 |
3 | using namespace std;
4 |
5 | struct CirNode{
6 | int data;
7 | struct CirNode* next;
8 | struct CirNode *prev;
9 | };
10 |
11 | struct CirNode* createNode(int data){
12 | // struct CirNode* p=(struct CirNode*)malloc(sizeof(struct CirNode));
13 | struct CirNode* p=new struct CirNode;
14 | p->data=data;
15 | p->next=NULL;
16 | p->prev=NULL;
17 | return p;
18 | }
19 |
20 | struct CirNode* inserthead(CirNode* head,int data){
21 | struct CirNode* add= createNode(data);
22 | if(head==NULL){
23 | add->next=add;
24 | add->prev=add;
25 | return add;
26 | }
27 | struct CirNode* p=head;
28 | struct CirNode* p1=head->next;
29 | while (p1!=head){
30 | p1=p1->next;
31 | }
32 | head=add;
33 | head->next=p;
34 | p1->next=head;
35 | head->prev=p1;
36 | p->prev=head;
37 | return head;
38 | }
39 |
40 | //尾插法
41 | struct CirNode* insertlast(CirNode* head,int data){
42 | struct CirNode* add= createNode(data);
43 | if(head==NULL){
44 | add->prev=add;
45 | add->next=add;
46 | return add;
47 | }
48 | struct CirNode* p=head;
49 | while(p->next!=head){
50 | p=p->next;
51 | }
52 | p->next=add;
53 | add->prev=p;
54 | add->next=head;
55 | return head;
56 | }
57 |
58 | struct CirNode* del(CirNode* head,int data){
59 | if(head==NULL){
60 | cout<<"链表没有数据"<data==data){
64 | struct CirNode* p=head->next;
65 | p->prev=head->prev;
66 | // free(head);
67 | delete head;
68 | return p;
69 | }
70 | struct CirNode* tail=head;
71 | struct CirNode* p=head->next;
72 | while (p!=head){
73 | if(p->data==data){
74 | tail->next=p->next;
75 | p->next->prev=tail;
76 | // free(p);
77 | delete p;
78 | return head;
79 | }
80 | tail=p;
81 | p=p->next;
82 | }
83 | }
84 |
85 | void printlist(CirNode* head){
86 | if(head==NULL){
87 | cout<<"链表没有数据"<data<<" ";
92 | p=p->next;
93 | } while (p!=head);
94 | cout<
2 | using namespace std;
3 | #define leftchild(i) (2*(i)+1) //定义宏函数,找到根节点的左孩子
4 |
5 | //构建堆
6 | void buildheap(int* an,int len,int index){
7 | int temp,child;
8 | for(temp=an[index];leftchild(index)an[child]){
11 | child++;
12 | }
13 | if(an[child]>temp){
14 | an[index]=an[child];
15 | }else{
16 | break;
17 | }
18 | }
19 | an[index]=temp;
20 | }
21 |
22 | //堆排序
23 | void heapsort(int* an,int len){
24 | for(int i=(len-1)/2;i>=0;i--){
25 | buildheap(an,len,i);
26 | }
27 | for(int i=len-1;i>0;i--){
28 | int temp=an[0];
29 | an[0]=an[i];
30 | an[i]=temp;
31 | buildheap(an,i,0);
32 | }
33 | }
34 |
35 | int main() {
36 | int an[]={7,8,9,10,1,-2,53,26,77,23,1034,-6};
37 | int len=sizeof(an)/sizeof(an[0]);
38 | heapsort(an,len);
39 | for(int i=0;i
2 | using namespace std;
3 |
4 | //插入排序
5 | void insertsort(int *an,int len){
6 | for(int i=1;i<=len-1;i++){
7 | int temp=an[i];
8 | int j;
9 | for(j=i;j>0&&an[j-1]>temp;j--){
10 | an[j]=an[j-1];
11 | }
12 | an[j]=temp;
13 | }
14 | }
15 |
16 | int main() {
17 | int an[]={7,8,9,10,1,-2,53,26,77,23,1034,-6};
18 | int len=sizeof(an)/sizeof(an[0]);
19 | insertsort(an,len);
20 | for(int i=0;i
2 | using namespace std;
3 |
4 | const int N=5e5+20;
5 | int n,m,s,a,b; //n为节点数,m为查询次数,s为根节点编号,a和b用于临时存储节点的临时变量
6 | int dep[N],p[N];
7 | vectorg[N]; //存储边集
8 |
9 | void dfs(int u,int d){
10 | dep[u]=d;
11 | int size=g[u].size();
12 | for(int i=0;idep[y]) x=p[x];
23 | while(x!=y){
24 | x=p[x];
25 | y=p[y];
26 | }
27 | return x;
28 | }
29 |
30 |
31 | int main() {
32 | cin>>n>>m>>s;
33 | for(int i=1;i>a>>b;
35 | g[a].emplace_back(b);
36 | g[b].emplace_back(a);
37 | }
38 | dfs(s,0);
39 | while(m--){
40 | cin>>a>>b;
41 | cout<
2 | using namespace std;
3 |
4 | const int N=5e5+20;
5 | int n,m,s,a,b; //n为节点数,m为查询次数,s为根节点编号,a和b用于临时存储节点的临时变量
6 | int dep[N],f[N][22]; //log2(N)算出来19,可以创建大于19的数组
7 | vectorg[N]; //存储边集
8 |
9 | void dfs(int u,int p,int d){
10 | dep[u]=d;
11 | f[u][0]=p;
12 | for(int i=1;i<=log2(dep[u]);++i){
13 | f[u][i]=f[f[u][i-1]][i-1];
14 | }
15 | int size=g[u].size();
16 | for(int i=0;i=0;--i){
28 | if((1<=0;--i){
32 | if(f[x][i]!=f[y][i]){
33 | x=f[x][i];
34 | y=f[y][i];
35 | }
36 | }
37 | return f[x][0];
38 | }
39 |
40 |
41 | int main() {
42 | cin>>n>>m>>s;
43 | for(int i=1;i>a>>b;
45 | g[a].emplace_back(b);
46 | g[b].emplace_back(a);
47 | }
48 | dfs(s,s,0);
49 | while(m--){
50 | cin>>a>>b;
51 | cout<
2 | using namespace std;
3 |
4 | struct heapNode{
5 | int data; //数据
6 | heapNode* left; //左子节点指针
7 | heapNode* right; //右子节点指针
8 | int Npl; //零路径长
9 | };
10 |
11 | class leftheap{
12 | public:
13 | leftheap(){
14 | root=new heapNode;
15 | root->left= nullptr;
16 | root->right= nullptr;
17 | root->data=INT_MAX;
18 | root->Npl=0;
19 | }
20 | heapNode* createNode(int data){
21 | auto p=new heapNode;
22 | p->data=data;
23 | p->left= nullptr;
24 | p->right= nullptr;
25 | p->Npl=0;
26 | return p;
27 | }
28 | heapNode* merge(heapNode* h1,heapNode* h2){
29 | if(h1->left== nullptr){
30 | h1->left=h2;
31 | }else{
32 | h1->right= findmerge_node(h1->right,h2);
33 | if(h1->left->Nplright->Npl){
34 | heapNode* p=h1->left;
35 | h1->left=h1->right;
36 | h1->right=p;
37 | }
38 | h1->Npl=h1->right->Npl+1;
39 | }
40 | return h1;
41 | }
42 | heapNode* findmerge_node(heapNode* h1,heapNode* h2){
43 | if(nullptr==h1){
44 | return h2;
45 | }else if(nullptr==h2){
46 | return h1;
47 | }
48 | if(h1->datadata){
49 | return merge(h1,h2);
50 | }else{
51 | return merge(h2,h1);
52 | }
53 | }
54 | void insert(int data){
55 | heapNode* add= createNode(data);
56 | if(root->data==INT_MAX){
57 | root=add;
58 | } else
59 | root=findmerge_node(root,add);
60 | }
61 | void delmin(){
62 | if(root== nullptr){
63 | return;
64 | }
65 | heapNode* h1=root->left;
66 | heapNode* h2=root->right;
67 | delete root;
68 | root= findmerge_node(h1,h2);
69 | }
70 | int getmin(){
71 | return root->data;
72 | }
73 | heapNode* print(heapNode* p){
74 | if(p!= nullptr){
75 | cout<data<<" ";
76 | print(p->left);
77 | print(p->right);
78 | }
79 | return p;
80 | }
81 | void print(){
82 | if(root== nullptr){
83 | return;
84 | }
85 | print(root);
86 | }
87 | private:
88 | heapNode* root;
89 | };
90 |
91 | int main() {
92 | leftheap h;
93 | h.insert(3);
94 | h.insert(10);
95 | h.insert(8);
96 | h.insert(17);
97 | h.insert(21);
98 | h.insert(14);
99 | h.insert(23);
100 | h.insert(26);
101 | h.delmin();
102 | cout<
2 | using namespace std;
3 |
4 |
5 | //合并操作
6 | void merge(int*an,int *temarr,int lpos,int rpos,int rightend){
7 | int leftend=rpos-1;
8 | int nums=(rightend-lpos)+1;
9 | int tempos=lpos;
10 | //进行比较lpos和rpos位上的元素
11 | while (lpos<=leftend&&rpos<=rightend){
12 | if(an[lpos]
2 | using namespace std;
3 |
4 | //希尔排序
5 | void shellsort(int *an,int len){
6 | for(int i=(len-1)/2;i>0;i/=2){
7 | //插入排序
8 | for(int j=i;j=i&&temp=len;k++);
35 | for(int d=Sedgewick[k];d>0;d=Sedgewick[++k]){
36 | for(int i=d;i=d&&an[j-d]>temp;j-=d){
40 | an[j]=an[j-d];
41 | }
42 | an[j]=temp;
43 | }
44 | }
45 | }
46 |
47 | int main() {
48 | int an[]={7,8,9,10,1,-2,53,26,77,23,1034,-6};
49 | int len=sizeof(an)/sizeof(an[0]);
50 | // shellsort(an,len);
51 | shellsort_pro(an,len);
52 | for(int i=0;i
2 | using namespace std;
3 |
4 | struct heapNode{
5 | int data;
6 | heapNode* left;
7 | heapNode* right;
8 | };
9 |
10 | class skewheap{
11 | public:
12 | skewheap(){
13 | root=new heapNode;
14 | root->data=INT_MAX;
15 | root->left= nullptr;
16 | root->right= nullptr;
17 | }
18 | heapNode* createNode(int data){
19 | auto p=new heapNode;
20 | p->data= data;
21 | p->left= nullptr;
22 | p->right= nullptr;
23 | return p;
24 | }
25 | heapNode* merge(heapNode* h1,heapNode* h2){
26 | if(h1->left== nullptr){
27 | h1->left=h2;
28 | }else{
29 | h1->right= findmerge_node(h1->right,h2);
30 | heapNode* p=h1->left;
31 | h1->left=h1->right;
32 | h1->right=p;
33 | }
34 | return h1;
35 | }
36 | heapNode* findmerge_node(heapNode* h1,heapNode* h2){
37 | if(nullptr==h1){
38 | return h2;
39 | }
40 | if(nullptr==h2){
41 | return h1;
42 | }
43 | if(h1->datadata){
44 | return merge(h1,h2);
45 | }else{
46 | return merge(h2,h1);
47 | }
48 | }
49 | void insert(int data){
50 | heapNode* add= createNode(data);
51 | if(root->data==INT_MAX){
52 | root=add;
53 | }else
54 | root=findmerge_node(root,add);
55 | }
56 | void delmin(){
57 | if(nullptr==root){
58 | return;
59 | }
60 | heapNode* h1=root->left;
61 | heapNode* h2=root->right;
62 | delete root;
63 | root= findmerge_node(h1,h2);
64 | }
65 | int getmin(){
66 | return root->data;
67 | }
68 | heapNode* print(heapNode* p){
69 | if(p!= nullptr){
70 | cout<data<<" ";
71 | print(p->left);
72 | print(p->right);
73 | }
74 | return p;
75 | }
76 | void print(){
77 | if(root== nullptr){
78 | return;
79 | }
80 | print(root);
81 | }
82 | private:
83 | heapNode* root;
84 | };
85 |
86 | int main() {
87 | skewheap h;
88 | h.insert(3);
89 | h.insert(10);
90 | h.insert(8);
91 | h.insert(17);
92 | h.insert(21);
93 | h.insert(14);
94 | h.insert(23);
95 | h.insert(26);
96 | h.delmin();
97 | h.print();
98 | system("pause");
99 | return 0;
100 | }
101 |
--------------------------------------------------------------------------------
/all/splay_tree.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | struct splay{
6 | int data;
7 | splay* left;
8 | splay* right;
9 | };
10 |
11 | splay* createNode(int data){
12 | auto p=new splay;
13 | p->data=data;
14 | p->left=NULL;
15 | p->right=NULL;
16 | return p;
17 | }
18 |
19 | splay* SingleRotatewithLeft(splay* &k1){
20 | splay* k2;
21 | k2=k1->left;
22 | k1->left=k2->right;
23 | k2->right=k1;
24 | return k2;
25 | }
26 |
27 | splay* SingleRotatewithRight(splay* &k1){
28 | splay* k2;
29 | k2=k1->right;
30 | k1->right=k2->left;
31 | k2->left=k1;
32 | return k2;
33 | }
34 |
35 | splay* DoubleRotatewithLeft(splay* &k1){
36 | k1->left= SingleRotatewithRight(k1->left);
37 | return SingleRotatewithLeft(k1);
38 | }
39 |
40 | splay* DoubleRotatewithRight(splay* &k1){
41 | k1->right= SingleRotatewithLeft(k1->right);
42 | return SingleRotatewithRight(k1);
43 | }
44 |
45 | //插入
46 | splay* insert(splay* &root,int data){
47 | if(NULL==root){
48 | splay* add= createNode(data);
49 | root=add;
50 | }else if(datadata){
51 | root->left= insert(root->left,data);
52 | }else if(data>root->data){
53 | root->right= insert(root->right,data);
54 | }
55 | return root;
56 | }
57 |
58 | //查找
59 | //因为查找data很有可能是相等的,所以要分开这种情况,如果root的下一个是要找的我们就往上返,令节点差为2个保证了判断路径结构的正确性
60 | splay* search(splay* &root,int data){
61 | if(NULL==root||root->data==data){
62 | return root;
63 | }else if(datadata){
64 | root->left= search(root->left,data);
65 | if(dataleft->data){
66 | root= SingleRotatewithLeft(root);
67 | }else if(data>root->left->data){
68 | root= DoubleRotatewithLeft(root);
69 | }
70 | }else if(data>root->data){
71 | root->right= search(root->right,data);
72 | if(data>root->right->data){
73 | root= SingleRotatewithRight(root);
74 | }else if(dataright->data){
75 | root= DoubleRotatewithRight(root);
76 | }
77 | }
78 | return root;
79 | }
80 |
81 | //查找最小值
82 | int findmin(splay* root){
83 | if(NULL==root){
84 | return root->data;
85 | }
86 | if (root->left!=NULL){
87 | return findmin(root->left);
88 | }else{
89 | return root->data;
90 | }
91 | }
92 |
93 | //查找最大值
94 | int findmax(splay* root){
95 | if(NULL==root){
96 | return root->data;
97 | }
98 | if(root->right!=NULL){
99 | return findmax(root->right);
100 | }else{
101 | return root->data;
102 | }
103 | }
104 |
105 | //删除树节点
106 | void del(splay* &root,int data){
107 | search(root,data);
108 | if(NULL==root){
109 | return;
110 | }else{
111 | splay* t1=root->left;
112 | splay* t2=root->right;
113 | root->left=NULL;
114 | root->right=NULL;
115 | delete root;
116 | int temp= findmax(t1);
117 | t1= search(t1,temp);
118 | t1->right=t2;
119 | root=t1;
120 | }
121 | }
122 |
123 | void inorderprint(splay* root){
124 | if(NULL==root){
125 | return;
126 | }
127 | inorderprint(root->left);
128 | cout<data<<" ";
129 | inorderprint(root->right);
130 | }
131 |
132 | //清空树
133 | void destroy(splay* &root){
134 | if(NULL==root){
135 | return;
136 | }
137 | destroy(root->left);
138 | destroy(root->right);
139 | delete root;
140 | }
141 |
142 | int main() {
143 | splay* root=NULL;
144 | insert(root,10);
145 | insert(root,3);
146 | insert(root,5);
147 | insert(root,6);
148 | insert(root,2);
149 | insert(root,8);
150 | search(root,8);
151 | // del(root,8);
152 | inorderprint(root);
153 | system("pause");
154 | return 0;
155 | }
156 |
--------------------------------------------------------------------------------
/all/stack.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/all/stack.cpp
--------------------------------------------------------------------------------
/all/topsort.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 |
5 | struct listnode{
6 | int data;
7 | listnode* next;
8 | };
9 |
10 | class graph{
11 | public:
12 | graph(int n){
13 | vnum=n;
14 | an=new listnode[n+1];
15 | indegree=(int*) malloc(sizeof(int)*(n+1));
16 | for(int i=0;idata=data;
25 | p->next= nullptr;
26 | return p;
27 | };
28 | void insert(int v,int data){
29 | auto add= createNode(data);
30 | if(an[v].next== nullptr){
31 | an[v].next=add;
32 | } else{
33 | listnode* p=an[v].next;
34 | while (p->next!= nullptr){
35 | p=p->next;
36 | }
37 | p->next=add;
38 | }
39 | indegree[data]++;
40 | }
41 | int findedgenull(){
42 | for(int i=1;i<=vnum;i++){
43 | if(indegree[i]==0){
44 | return i;
45 | }
46 | }
47 | return 0;
48 | }
49 | //拓扑排序
50 | void topsort(){
51 | queueq;
52 | int v=findedgenull();
53 | if(v==0){
54 | cout<<"该图含有圈"<data]==0){
69 | q.push(p->data);
70 | }
71 | p=p->next;
72 | }
73 | }
74 | cout<i,wi+1)∈E,1 散列函数特性:
22 | >
23 | > 1. 简单快速
24 | > 2. 均匀性:需要让关键字均匀分布在哈希表中
25 |
26 | - 用于将关键字值**映射**到数组中的一个函数,一般的方法为**关键字%表的大小**
27 | - 该函数我们需要**在单元之间均匀地分配关键字**,好的办法就是表的大小是**素数**,这将让散列函数算起来简单并且关键字分配比较均匀
28 | - 如果关键字是**字符串**的时候,通常我们**将字符串中的每个字符转换为ASCII码并求和**,得到一个int型的数,就可以对它进行散列函数映射到哈希表中,一个更好的方法是:根据horner法则,计算一个**(32的)多项式函数**。
29 | - **多个**关键字**映射**到**同一个**数组下标或者数组单元的情况叫做**冲突**
30 |
31 |
32 |
33 | **常用哈希函数**:
34 |
35 | 1. 关键字是字符串:根据horner法则,计算一个(32的)多项式函数。
36 |
37 | **介绍**:如果**关键字特别长**,那么散列函数计算起来会花过多的时间,而且前面的字符还会左移出最终的结果。因此这样情况下,**不使用所有的字符**。此时**关键字的长度和性质会影响选择**。例如只取奇数位置上的字符来实现散列函数。这里的思想是用计算散列函数省下来的时间来补偿由此产生的对均匀分布函数的轻微干扰
38 |
39 | ```c++
40 | int hash(const char* key,int tablesize){
41 | unsigned int hashval=0;
42 | while(*key!='\0'){
43 | hashval=(hashval<<5)+*key; //右移五次等于乘2的五次方也就是32
44 | }
45 | return hashval%tablesize;
46 | }
47 | ```
48 |
49 |
50 |
51 | 2. **直接寻址法**
52 | **介绍**:取**关键字或关键字的某个线性函数值为散列地址**,即**H(key)=key或者H(key)=a*key+b(a,b为常数)。**
53 | 举例:[‘A’,‘B’,‘D’,‘A’,‘C’,‘E’,‘F’,‘C’] ,求该字符数组里每个字符的出现次数(数组中只有大写字母)。
54 | 分析:我们可以知道’A’-'Z’的ASCLL码是65-90,则哈希函数可以通过直接寻址法H(key)=key-‘A’(对应定义中的a=1,b=-‘A’即65),这样针对每一个key,都可以将它的H(key)值当成数组下标放在一个长度为26的int数组中统计长度
55 | 假设字符数组为a,int数组为b。即b[a[i]-‘A’]++(i表示a数组的下标索引)。
56 | 结果
57 | b[0]=2(代表A出现两次);b[1]=1(代表B出现一次),b[2]=2(代表C出现两次)…
58 |
59 |
60 |
61 | 3. **数字分析法**
62 | **介绍**:**分析一组数据中相同位(个位,十位,百位…)的数字出现频率**,如果该位数字**出现结果较为集中**,如果**取其作为构造散列地址的依据则很容易出现哈希冲突**,反之,**如果该位数字出现结果较为平均,则取其作为构造散列地址的依据则不容易出现哈希冲突。**
63 | 举例:某公司招聘了一些实习生,其生日分别为[19990104,20000910,20000315,20001128,20001014,19990413,19990920,20000517],对其进行hash处理。
64 | 分析
65 | 如果取8位数作为散列地址,虽然很难出现哈希冲突,但是空间浪费很大,因此考虑只取其中几位作为散列地址,即能减少空间浪费又能降低哈希冲突的可能性,观察上面8组数据,前4位集中在1999,2000,如果取前4位则很容易出现哈希冲突,而后四位分布相对分散,不容易出现哈希冲突,因此取后四位比较符合。
66 | 结果
67 | H(19990104)=104,H(20000910)=910,H(20000315)=315…
68 |
69 |
70 |
71 | 4. **折叠法**
72 | **介绍**:折叠法是把**关键字值分成自左向右分成位数相等的几部分**,**每一部分的位数应与散列表地址(也就是数组下标)的位数相同**,只有**最后一部分的位数可以短一些**。把**这些部分的数据叠加起来(去除进位)**,就可以得到关键字值的散列地址。
73 | 有两种叠加方法:
74 | (1)**移位法(shift floding)**:把各部分的最后一位对齐相加。
75 | (2)**分界法(floding at the boudaries)**:沿各部分的分界来回折叠(即第偶数个加数和移位法反过来),然后对其相加。
76 | 举例:key=1234791,散列地址为2位
77 | 分析
78 | 将key分成12,34,79,1四部分
79 | (1)移位法:12+34+79+1
80 | (2)分界法:12+43+79+1(即第偶数个加数和移位法反过来)
81 | 结果
82 | (1)移位法:H(1234791)=35(相加为135,去除进位1)
83 | (2)分界法:H(1234791)=44(相加为144,去除进位1)
84 |
85 |
86 |
87 | 5. **平方取中法**
88 | **介绍**:当**无法确定关键字中哪几位分布较均为时**,可以**求出关键字的平方值,然后按需要取平方值的中间几位作为散列地址**。这是因为:平方后中间几位和关键字中每一位都有关,故不同关键字会以较高的概率产生不同的散列地址。
89 | 举例:关键字序列:{3213,3113,3212,4312}。
90 | 分析:
91 | 3213^2=10323369
92 | 3113^2=9690769
93 | 3212^2=10316944
94 | 4312^2=18593344
95 | 取平方值中间4位为散列地址(3113的平方值前面补0凑成8位)
96 | 结果
97 | H(3213)=3233,H(3113)=6907,H(3212)=3169,H(4312)=5933
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | ## 解决冲突
108 |
109 | - **负载因子(local factor)**为**散列表中的元素个数与散列表的大小的比值**。
110 |
111 | >1. 负载因子为0.7-0.75比较合理,负载因子在哈希表中的意义就是当你这个哈希表的负载因子达到你设定的值就进行扩容为后面的存储更多数据做准备。
112 | >2. java封装的数据结构也是使用的分离链接法,但是其不同的是,他不是完全的数组加链表的形式,它是当**链表达到一定长度时就将链表转化为红黑树**。
113 | >3. java封装的哈希表的数据结构的负载因子为什么为0.75呢
114 | >
115 | > - 是因为**当负载因子等于1**的时候也就意味着关键字均匀分布并且几乎存满了哈希表(数组的每个下标都有关键字填充)才进行扩容的情况,关键字数量多就会**造成大量的哈希冲突**,这也造成了数组加红黑树的情况出现的更多,而这样**底层的红黑树变得更加复杂**,**大大降低了查询速度**,这种情况就是**牺牲了时间来保证空间的利用率.**
116 | > - 当**负载因子为0.5**时,也就意味着**当数组中的元素达到一半就开始扩容**,虽然填充的元素少了,哈希冲突减少了,查询速度提高了,但是**空间利用率降低了**,原本1m的数据现在需要2m的空间存储,这就是**牺牲空间来保证时间的效率**
117 | > - 当**负载因子为0.75**,**时间和空间达到了平衡**,所以java封装的哈希表结构的负载因子默认为0.75.
118 |
119 |
120 |
121 |
122 |
123 | - **分离链接法**:就是一个**数组加链表**来解决冲突问题的,将映射到同一个数组下标的所有关键字保留在一个表中,而这个表就是链表,**将同一个数组下标的所有关键字通过链表连接起来**,该方法使用的比较多。分离链接散列的基本法则是**使得表的大小尽量与预料的关键字个数差不多**(也就是**负载因子约等于1**),这样也就是能够**保证关键字均匀分布在散列表中**,使得查找时间减少。
124 |
125 | >1. **插入**:插入时可以选择头插法插入链表中,如果插入重复元素,定义链表时可以选择多增加一个计数的域,来记录这个元素出现次数
126 | >2. **查找**:对要查找的关键字进行哈希函数的操作,得到映射的数组下标,然后在该下标指向的链表中查找指定关键字
127 | >3. **删除**:找到对应的数组下标,遍历链表找到要删除的关键字的节点,然后判断它的存储个数(cnt),如果大于1就让cnt-1,如果等于1就是删除该节点
128 | >4. **缺点**:需要指针,给新单元分配空间需要时间,导致算法的速度减慢,与此同时还需要对链表的数据结构进行实现。
129 |
130 | ```c++
131 | //分离链接法
132 | //定义链表
133 | template
134 | struct listnode{
135 | T data;
136 | listnode* next;
137 | int cnt;
138 | };
139 |
140 |
141 | template
142 | class hashtable{
143 | public:
144 | int isPrime(int num) {
145 | if(num <= 1) {
146 | return 0;
147 | }
148 | int i;
149 | for(i = 2; i*i <= num; i++) {
150 | if(num % i == 0) {
151 | return 0;
152 | }
153 | }
154 | return 1;
155 | }
156 | //找出大于tablesize最近的素数
157 | int prime(int size){
158 | while (!isPrime(size)) {
159 | size++;
160 | }
161 | return size;
162 | }
163 | float loadfactor(){
164 | return (float)count/(float)tablesize;
165 | }
166 | listnode* createNode(T data){
167 | listnode* list=(listnode*)malloc(sizeof(listnode));
168 | list->data=data;
169 | list->next= nullptr;
170 | list->cnt=1;
171 | return list;
172 | }
173 | hashtable(int size){
174 | this->count=0;
175 | this->tablesize=prime(size);
176 | for(int i=0;i< this->tablesize;i++){
177 | listnode*list=(listnode*)malloc(sizeof(listnode));
178 | list->next=NULL;
179 | list->cnt=0;
180 | v.push_back(list);
181 | }
182 | }
183 | //散列函数(哈希函数),用于将关键字处理得到映射的数组下标,这里用了简单的哈希函数,在不同场景有不同的函数设计
184 | int hash(T data){
185 | return data%this->tablesize;
186 | }
187 |
188 | listnode* findnode(listnode* head,T data){
189 | if(head!= nullptr){
190 | listnode* p=head;
191 | while (p!= nullptr){
192 | if(p->data==data){
193 | return p;
194 | }
195 | p=p->next;
196 | }
197 | }
198 | return NULL;
199 | }
200 |
201 | void insert(T data){
202 | if(loadfactor()>1||loadfactor()==1){
203 | int size= this->tablesize;
204 | this->tablesize=prime(count*2);
205 | for(int i=size;i< this->tablesize;i++){
206 | listnode*list=(listnode*)malloc(sizeof(listnode));
207 | list->next=NULL;
208 | list->cnt=0;
209 | v.push_back(list);
210 | }
211 | }
212 | int index= hash(data);
213 | if(nullptr==v[index]->next){
214 | listnode* list= createNode(data);
215 | v[index]->next=list;
216 | } else{
217 | listnode* tail=findnode(v[index]->next,data);
218 | if(tail==NULL){
219 | listnode* list= createNode(data);
220 | listnode* p=v[index]->next;
221 | v[index]->next=list;
222 | v[index]->next->next=p;
223 | }else{
224 | tail->cnt++;
225 | }
226 | }
227 | this->count++;
228 | }
229 | listnode* find(T data){
230 | int index= hash(data);
231 | listnode* p=findnode(v[index]->next,data);
232 | return p;
233 | }
234 | void print(){
235 | for(int i=0;i< this->tablesize;i++){
236 | listnode* p=v[i]->next;
237 | cout<<"索引为"<cnt;j++)
244 | cout<data<<" ";
245 | p=p->next;
246 | }
247 | cout<* tail=v[index]->next;
253 | listnode* p=v[index];
254 | while (tail->next!= nullptr){
255 | if(tail->data==data){
256 | break;
257 | }
258 | p=tail;
259 | tail=tail->next;
260 | }
261 | if(tail->data==data){
262 | if(tail->cnt>1){
263 | tail->cnt--;
264 | count--;
265 | return;
266 | }
267 | p->next=tail->next;
268 | delete tail;
269 | count--;
270 | }
271 | return;
272 | }
273 | private:
274 | int count;
275 | vector*>v;
276 | int tablesize;
277 | };
278 | ```
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 | - **开放定址法**:该算法的结构就只有**一个数组**。如果有**哈希冲突发生**,那么就尝试**选择其他的单元**,直到**找到空单元就进行插入**。函数F是冲突解决的办法。对于开放定址法来说,**负载因子应该低于0.5**(只要表足够大,这样总能够找到一个空单元才能解决冲突),而该方法的**删除操作建议是懒惰删除**,也就是**删除对应的值,但是数组的长度不会变**。开放地址法也分为三个方法:
287 |
288 | >1. **线性探测法**:通过哈希函数,找到关键字对应的数组下标,如果**该单元非空**,则我们进行向后查找(**也就是在这个数组下标的后面进行查找空单元**),如果**达到数组的最后一个单元都没找到空单元**就**返回到数组的第一个单元(也就是数组下标为0)再进行向后查找**;如果**该单元是空单元**,则**直接进行插入**。如果表可以多于一半被填满,线性探测就不是好方法,**如果元素较少使用线性探测法**,如果数据量大就不建议使用
289 | >2. **平方探测法**:是用来消除线性探测中一次聚集问题的冲突解决方法,平方探测法就是冲突函数为二次函数的探测方法,**流行的选择是F(i)=i2(i为冲突次数)**,通过哈希函数,找到关键字对应的数组下标,如果该**单元是空的就插入**,如果**该单元非空**,则**该单元的冲突次数+1也就是i=1**,通过**F(i)计算得到向后移动的单元**,所以算出等于1就向后移动一单元,如果所处的单元还是非空,则冲突次数再次+1,然后再向后移动F(i)位,i为2则移动四个单元(**移动的单元不是从所处的单元在移动4位,而是从原本的单元也就是开始通过哈希函数计算出来的单元开始移动四位**),如此**递推下去,直到找到空的单元**,如果**达到最后一单元**,则从**数组下标0重新开始**。
290 | >3. **双散列**:双散列的意思是映射数组下标时,使用**两个散列函数进行计算映射位置**,对于双散列,**流行的一种选择是F(i)=i*hash2(X)**,hash2(X)为第二个哈希函数,i为探测次数,也就是当我**插入时**,通过**第一个哈希函数计算出映射的数组下标**,如果该单元是**空单元**,就**直接插入**,如果**非空**,则**通过第二哈希函数计算向后移动的位数**,比方说,当我插入映射到数组下标8的位置,但是下标为8的单元非空,则需要向后移动,而此时i为1,然后通过哈希2计算出移动位置,如果移动后的单元还是非空,则此时i等于2,计算出移动位数后,需要重新回到数组下标8进行移动,直到找到空单元为止。**哈希2函数的选取很重要**,如果选择的不好则将会是灾难性的,像**hash2(X)=R-(X mod R)这种函数会比较好**,R的选择需要根据情况设定,然后**保证表的大小为素数很重要**
291 |
292 | - **再散列**:对于**使用平方探测的开放定址法**,如果**表的元素填的太满**,性能则会大大降低,则我们就**新建立一个原来的散列表的两倍大小的散列表(并且使用一个相关的新散列函数)**,然后**扫描原始的散列表**,通过新的散列函数**计算每个已经插入在原表中的数据的新的映射下标并将其插入新表之中**,双散列建立的时机可以实时根据负载因子决定,当负载因子到达指定值就进行再散列操作。
293 |
294 | ```c++
295 | //开放定址法
296 | class hashtable{
297 | public:
298 | bool isprime(int n){
299 | if(n<=1)
300 | return false;
301 | for(int i=2;i*itablesize= prime(size);
317 | for(int i=0;i1){
327 | cout<<"没有空余的位置插入"<1){
346 | cout<<"没有空余的位置插入"<tablesize-1){
354 | i++;
355 | index=index-tablesize;
356 | }
357 | }
358 | return index;
359 | }
360 | float localfactor(){
361 | return (float)count/(float)tablesize;
362 | }
363 | void insert(int key){
364 | if(localfactor()>0.5||localfactor()==0.5){
365 | int size=tablesize*2;
366 | for(int i=tablesize;iv;
409 | int tablesize;
410 | };
411 | ```
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 | - **可扩散列**:当**处理数据量太大以至于装不进主存的情况下**,此时主要**考虑是检索数据所需的磁盘存取次数**,而可扩散列,它允许用两次磁盘访问就能够执行一次查找操作,插入操作也是很少的磁盘访问。可扩散列有点**类似于B树的结构**。**可扩散列无法存在重复关键字**
424 |
425 | > 1. 在可扩散列中,我们用**D表示根所使用的比特数(也称其为目录)**,**目录的所存的元素个数为2D**,**dL为树叶节点中的元素共有的最高位位数,因此dL应该小于等于D**
426 | > 2. **D就是用来区分存储节点的位置的依据**,例如我们的数据由前俩个比特进行区分,则该结构的节点应该能够存储4个元素,然后dL应该等于2,因为数据需要根据前两位跟目录的元素进行匹对来存储到对应的节点,因此它的共有最高位应该为2,如图5-23
427 | > 3. 如果插入数据时,**节点元素已经满了,我们就需要进行分裂节点来存储**,例如上述讲的图5-23当D=2时,我们插入100100时,发现10为根节点的叶子节点元素已经满了,就分裂该叶子节点,分裂完发现根节点也满了则需要对根节点分裂,**因此根节点分裂后应该以3比特进行将数据分开存储,因为23等于8,因此根节点分裂后为8个元素(如图5-24)**,但是**叶子节点只有5个**,因此有**一些根节点跟其他根节点共用一个叶子节点,直到再次插入让它们共用的节点,才进行更改根节点指向(如图5-25)。**
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
--------------------------------------------------------------------------------
/hashtable(哈希表)/hashtable--1.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/hashtable(哈希表)/hashtable--1.cpp
--------------------------------------------------------------------------------
/hashtable(哈希表)/hashtable--2.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/hashtable(哈希表)/hashtable--2.cpp
--------------------------------------------------------------------------------
/heap(堆)/heap(堆).md:
--------------------------------------------------------------------------------
1 | # 堆(优先队列)
2 |
3 | ## 二叉堆
4 |
5 | **概念**:
6 |
7 | - 优先队列是一个根据优先性而先去执行操作的一种特殊队列,平常队列是先进先出,但是优先队列是根据优先级选择先出的元素。优先队列的主要操作有插入和删除最小值
8 |
9 | - **堆(heap)**通常是指**二叉堆**,因为二叉堆的使用次数最频繁,所以我们平常认为的堆就是二叉堆
10 |
11 | - **二叉堆**:二叉堆是由**一颗完全二叉树实现**的,完全二叉树是**一颗底层必须从左往右依次插入且底层以上的节点都是填满的树(最后一层也就是叶子节点可以不是填满的,但是已经插入的元素必须是从左到右的中间不空缺元素的)**称为完全二叉树
12 |
13 | - 完全二叉树是一个**很有规律的树**,因此**用一个动态数组实现是效率最好的选择**,在动态数组中是按照**从上到下从左到右依次插入数组**中,数组下标为0处不放元素。
14 |
15 | >用数组实现的完全二叉树的性质有:
16 | >
17 | >1. 对于**数组中任意一个位置i上的元素**,其**左儿子在数组位置2i上**,**右儿子在**左儿子后的单元也就是**数组下标为(2i+1)的位置**,它的**父亲在i/2的位置上**。
18 | >2. **数组下标为0的地方是不放我们要存的元素的**
19 |
20 |
21 |
22 | **性质**:
23 |
24 | - 堆也就是通常认为的二叉堆(binary heap),是由一颗完全二叉树实现的
25 | - 堆中的主要操作有插入和删除最小值操作,**堆的删除其实就是删除最小值而不是删除指定值**
26 | - 堆有**堆序性质**,也就是**堆中的任意子树也是一个堆**,因此**任意节点就应该小于它的子节点**,因为堆需要快速查找最小元,因此**我们将最小元放在根节点上**。
27 | - 其**结构体**应该包含**一个数组(动态)**,**堆中存储的有效元素个数**,**数组的容量**以便于扩容
28 |
29 |
30 |
31 | **最大堆/大根堆**:任意节点应该**大于**它的所有后裔
32 |
33 | **最小堆/小根堆**:任意节点应该**小于**它的所有后裔
34 |
35 |
36 |
37 | **插入操作(上浮)**:
38 |
39 | - 先遵从**堆从上到下,从左到右依次插入**,我们将数据按照这个准则插入到数组。
40 | - 然而,插入后,我们还需要进行**检查这个堆是否有堆序性**,如果没有就需要进行调整
41 | - **插入数据跟根节点进行比较,如果根节点的值比插入数据大,就需要交换,然后一路向上检查比较,直到根节点。**
42 |
43 |
44 |
45 | **删除操作(下沉)**:
46 |
47 | - 堆的**删除操作是删除最小值的操作**,而不是删除指定值的操作
48 | - 我们创建堆时,都将**最小值放到根节点**,因此删除我们只需要将根节点删除掉
49 | - 但是删除根节点后,我们的堆序性就无法保证,如何保证堆序性以及堆的性质(也就是完全二叉树的性质)呢
50 | - 我们**需要将根节点的值与叶子层的最右边元素进行交换**,然后**删除交换后处在叶子节点(也就是原来的根节点)的节点**,然后让**现在的根节点跟左右子节点的最小节点比较**,如果**大于就交换,直到检查到叶子节点**,则就调整成功了。
51 |
52 |
53 |
54 |
55 |
56 | **构建堆**
57 |
58 | - 构建堆的操作就**是将一个无序的树,构造成一个堆**
59 | - 一个堆满足完全二叉树的特性以及堆序性,因此我们**需要对这个无序树进行调整**,让其成为一个堆。
60 |
61 |
62 |
63 |
64 |
65 | 实现代码:
66 |
67 | ```c++
68 | class heap{
69 | public:
70 | heap(int maxsize){
71 | key=new int[maxsize+1];
72 | key[0]=0;
73 | for(int i=1;i0){
92 | int i=index;
93 | index=index/2;
94 | if(key[index]>key[i]){
95 | int temp=key[index];
96 | key[index]=key[i];
97 | key[i]=temp;
98 | }
99 | }
100 | }
101 | void insert(int data){
102 | if(size==capacity){
103 | int *an=new int[2*capacity];
104 | capacity=capacity*2;
105 | for(int i=0;i<=size;i++){
106 | an[i]=key[i];
107 | }
108 | delete[] key;
109 | key=an;
110 | }
111 | if(key[1]==0){
112 | key[1]=data;
113 | }else{
114 | adjust(data);
115 | }
116 | size++;
117 | }
118 | void deladjust(int index){
119 | if(index*2<=size){
120 | int mn;
121 | if(key[index*2+1]==NULL){
122 | mn=index*2;
123 | }
124 | else if(key[index*2]>key[index*2+1]){
125 | mn=index*2+1;
126 | }else{
127 | mn=index*2;
128 | }
129 | if(key[index]>key[mn]){
130 | int temp=key[index];
131 | key[index]=key[mn];
132 | key[mn]=temp;
133 | }
134 | deladjust(mn);
135 | }
136 | return;
137 | }
138 | void delmin(){
139 | key[1]=key[size];
140 | key[size]=0;
141 | size--;
142 | deladjust(1);
143 | }
144 | void destroy(){
145 | for(int i=1;i<=size;i++){
146 | key[i]=0;
147 | }
148 | size=0;
149 | cout<<"成功清除堆中数据"<r-1个节点
212 | - 对左式堆的右路径的插入和合并操作可能会破坏左式堆的性质,需要进行调整
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 | **合并操作**
221 |
222 | - 插入其实就是合并的一个特殊情况
223 | - 如果两个左式堆合并,有一个堆为空就返回另外一个堆,否则**比较两个堆的根值**
224 | - **递归进去**,我们**将大的根值的堆与小的根值的堆的右子堆合并**
225 | - 然后递归返回后,**将新的堆作为原来小的根值的堆的右孩子(也叫合并)**。
226 | - **如果这样形成的堆的右子堆的零路径长大于左子堆的,就将左子堆跟右子堆交换,并且更新零路径长,就完成了合并的操作。**
227 |
228 |
229 |
230 |
231 |
232 | 实现代码:
233 |
234 | ```c++
235 | #include
236 | using namespace std;
237 |
238 | struct heapNode{
239 | int data; //数据
240 | heapNode* left; //左子节点指针
241 | heapNode* right; //右子节点指针
242 | int Npl; //零路径长
243 | };
244 |
245 | class leftheap{
246 | public:
247 | leftheap(){
248 | root=new heapNode;
249 | root->left= nullptr;
250 | root->right= nullptr;
251 | root->data=INT_MAX;
252 | root->Npl=0;
253 | }
254 | heapNode* createNode(int data){
255 | auto p=new heapNode;
256 | p->data=data;
257 | p->left= nullptr;
258 | p->right= nullptr;
259 | p->Npl=0;
260 | return p;
261 | }
262 | heapNode* merge(heapNode* h1,heapNode* h2){
263 | if(h1->left== nullptr){
264 | h1->left=h2;
265 | }else{
266 | h1->right= findmerge_node(h1->right,h2);
267 | if(h1->left->Nplright->Npl){
268 | heapNode* p=h1->left;
269 | h1->left=h1->right;
270 | h1->right=p;
271 | }
272 | h1->Npl=h1->right->Npl+1;
273 | }
274 | return h1;
275 | }
276 | heapNode* findmerge_node(heapNode* h1,heapNode* h2){
277 | if(nullptr==h1){
278 | return h2;
279 | }else if(nullptr==h2){
280 | return h1;
281 | }
282 | if(h1->datadata){
283 | return merge(h1,h2);
284 | }else{
285 | return merge(h2,h1);
286 | }
287 | }
288 | void insert(int data){
289 | heapNode* add= createNode(data);
290 | if(root->data==INT_MAX){
291 | root=add;
292 | } else
293 | root=findmerge_node(root,add);
294 | }
295 | void delmin(){
296 | if(root== nullptr){
297 | return;
298 | }
299 | heapNode* h1=root->left;
300 | heapNode* h2=root->right;
301 | delete root;
302 | root= findmerge_node(h1,h2);
303 | }
304 | int getmin(){
305 | return root->data;
306 | }
307 | heapNode* print(heapNode* p){
308 | if(p!= nullptr){
309 | cout<data<<" ";
310 | print(p->left);
311 | print(p->right);
312 | }
313 | return p;
314 | }
315 | void print(){
316 | if(root== nullptr){
317 | return;
318 | }
319 | print(root);
320 | }
321 | private:
322 | heapNode* root;
323 | };
324 | ```
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 | ## 斜堆
339 |
340 | **概念**:
341 |
342 | - **斜堆**是**左式堆的自调节形式**,斜堆和左式堆间的关系类似于伸展树和AVL树间的关系
343 | - 斜堆是**具有堆序性的二叉树**,但是**不存在对树的结构限制**
344 | - 不同于左式堆,**关于任意节点的零路径长的任何信息都不保留,因为斜堆的右路径在任何时刻都可以任意长**
345 |
346 |
347 |
348 |
349 |
350 | **合并操作**
351 |
352 | - 斜堆的合并大概都跟左式堆的合并操作一样,但是交换操作不一样,**斜堆的交换是无条件的**
353 | - **就是说当进行将大的根值的堆与小的根值的堆的右子堆合并后,我们就需要进行左子树跟右子树交换的操作,并不是只有到最后小的根值的堆跟新的堆合并后在进行交换**
354 | - 就是**每个合并的步骤就需要交换左右子树**。
355 |
356 |
357 |
358 |
359 |
360 | 实现代码:
361 |
362 | ```c++
363 | struct heapNode{
364 | int data;
365 | heapNode* left;
366 | heapNode* right;
367 | };
368 |
369 | class skewheap{
370 | public:
371 | skewheap(){
372 | root=new heapNode;
373 | root->data=INT_MAX;
374 | root->left= nullptr;
375 | root->right= nullptr;
376 | }
377 | heapNode* createNode(int data){
378 | auto p=new heapNode;
379 | p->data= data;
380 | p->left= nullptr;
381 | p->right= nullptr;
382 | return p;
383 | }
384 | heapNode* merge(heapNode* h1,heapNode* h2){
385 | if(h1->left== nullptr){
386 | h1->left=h2;
387 | }else{
388 | h1->right= findmerge_node(h1->right,h2);
389 | heapNode* p=h1->left;
390 | h1->left=h1->right;
391 | h1->right=p;
392 | }
393 | return h1;
394 | }
395 | heapNode* findmerge_node(heapNode* h1,heapNode* h2){
396 | if(nullptr==h1){
397 | return h2;
398 | }
399 | if(nullptr==h2){
400 | return h1;
401 | }
402 | if(h1->datadata){
403 | return merge(h1,h2);
404 | }else{
405 | return merge(h2,h1);
406 | }
407 | }
408 | void insert(int data){
409 | heapNode* add= createNode(data);
410 | if(root->data==INT_MAX){
411 | root=add;
412 | }else
413 | root=findmerge_node(root,add);
414 | }
415 | void delmin(){
416 | if(nullptr==root){
417 | return;
418 | }
419 | heapNode* h1=root->left;
420 | heapNode* h2=root->right;
421 | delete root;
422 | root= findmerge_node(h1,h2);
423 | }
424 | int getmin(){
425 | return root->data;
426 | }
427 | heapNode* print(heapNode* p){
428 | if(p!= nullptr){
429 | cout<data<<" ";
430 | print(p->left);
431 | print(p->right);
432 | }
433 | return p;
434 | }
435 | void print(){
436 | if(root== nullptr){
437 | return;
438 | }
439 | print(root);
440 | }
441 | private:
442 | heapNode* root;
443 | };
444 |
445 | ```
446 |
447 |
--------------------------------------------------------------------------------
/heap(堆)/heap.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/heap(堆)/heap.cpp
--------------------------------------------------------------------------------
/heap(堆)/leftlist-heaps.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | struct heapNode{
5 | int data; //数据
6 | heapNode* left; //左子节点指针
7 | heapNode* right; //右子节点指针
8 | int Npl; //零路径长
9 | };
10 |
11 | class leftheap{
12 | public:
13 | leftheap(){
14 | root=new heapNode;
15 | root->left= nullptr;
16 | root->right= nullptr;
17 | root->data=INT_MAX;
18 | root->Npl=0;
19 | }
20 | heapNode* createNode(int data){
21 | auto p=new heapNode;
22 | p->data=data;
23 | p->left= nullptr;
24 | p->right= nullptr;
25 | p->Npl=0;
26 | return p;
27 | }
28 | heapNode* merge(heapNode* h1,heapNode* h2){
29 | if(h1->left== nullptr){
30 | h1->left=h2;
31 | }else{
32 | h1->right= findmerge_node(h1->right,h2);
33 | if(h1->left->Nplright->Npl){
34 | heapNode* p=h1->left;
35 | h1->left=h1->right;
36 | h1->right=p;
37 | }
38 | h1->Npl=h1->right->Npl+1;
39 | }
40 | return h1;
41 | }
42 | heapNode* findmerge_node(heapNode* h1,heapNode* h2){
43 | if(nullptr==h1){
44 | return h2;
45 | }else if(nullptr==h2){
46 | return h1;
47 | }
48 | if(h1->datadata){
49 | return merge(h1,h2);
50 | }else{
51 | return merge(h2,h1);
52 | }
53 | }
54 | void insert(int data){
55 | heapNode* add= createNode(data);
56 | if(root->data==INT_MAX){
57 | root=add;
58 | } else
59 | root=findmerge_node(root,add);
60 | }
61 | void delmin(){
62 | if(root== nullptr){
63 | return;
64 | }
65 | heapNode* h1=root->left;
66 | heapNode* h2=root->right;
67 | delete root;
68 | root= findmerge_node(h1,h2);
69 | }
70 | int getmin(){
71 | return root->data;
72 | }
73 | heapNode* print(heapNode* p){
74 | if(p!= nullptr){
75 | cout<data<<" ";
76 | print(p->left);
77 | print(p->right);
78 | }
79 | return p;
80 | }
81 | void print(){
82 | if(root== nullptr){
83 | return;
84 | }
85 | print(root);
86 | }
87 | private:
88 | heapNode* root;
89 | };
90 |
91 | int main() {
92 | leftheap h;
93 | h.insert(3);
94 | h.insert(10);
95 | h.insert(8);
96 | h.insert(17);
97 | h.insert(21);
98 | h.insert(14);
99 | h.insert(23);
100 | h.insert(26);
101 | h.delmin();
102 | cout<
2 | using namespace std;
3 |
4 | struct heapNode{
5 | int data;
6 | heapNode* left;
7 | heapNode* right;
8 | };
9 |
10 | class skewheap{
11 | public:
12 | skewheap(){
13 | root=new heapNode;
14 | root->data=INT_MAX;
15 | root->left= nullptr;
16 | root->right= nullptr;
17 | }
18 | heapNode* createNode(int data){
19 | auto p=new heapNode;
20 | p->data= data;
21 | p->left= nullptr;
22 | p->right= nullptr;
23 | return p;
24 | }
25 | heapNode* merge(heapNode* h1,heapNode* h2){
26 | if(h1->left== nullptr){
27 | h1->left=h2;
28 | }else{
29 | h1->right= findmerge_node(h1->right,h2);
30 | heapNode* p=h1->left;
31 | h1->left=h1->right;
32 | h1->right=p;
33 | }
34 | return h1;
35 | }
36 | heapNode* findmerge_node(heapNode* h1,heapNode* h2){
37 | if(nullptr==h1){
38 | return h2;
39 | }
40 | if(nullptr==h2){
41 | return h1;
42 | }
43 | if(h1->datadata){
44 | return merge(h1,h2);
45 | }else{
46 | return merge(h2,h1);
47 | }
48 | }
49 | void insert(int data){
50 | heapNode* add= createNode(data);
51 | if(root->data==INT_MAX){
52 | root=add;
53 | }else
54 | root=findmerge_node(root,add);
55 | }
56 | void delmin(){
57 | if(nullptr==root){
58 | return;
59 | }
60 | heapNode* h1=root->left;
61 | heapNode* h2=root->right;
62 | delete root;
63 | root= findmerge_node(h1,h2);
64 | }
65 | int getmin(){
66 | return root->data;
67 | }
68 | heapNode* print(heapNode* p){
69 | if(p!= nullptr){
70 | cout<data<<" ";
71 | print(p->left);
72 | print(p->right);
73 | }
74 | return p;
75 | }
76 | void print(){
77 | if(root== nullptr){
78 | return;
79 | }
80 | print(root);
81 | }
82 | private:
83 | heapNode* root;
84 | };
85 |
86 | int main() {
87 | skewheap h;
88 | h.insert(3);
89 | h.insert(10);
90 | h.insert(8);
91 | h.insert(17);
92 | h.insert(21);
93 | h.insert(14);
94 | h.insert(23);
95 | h.insert(26);
96 | h.delmin();
97 | h.print();
98 | system("pause");
99 | return 0;
100 | }
101 |
--------------------------------------------------------------------------------
/images/image-20230530074746459.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230530074746459.png
--------------------------------------------------------------------------------
/images/image-20230530231044041.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230530231044041.png
--------------------------------------------------------------------------------
/images/image-20230530234156315.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230530234156315.png
--------------------------------------------------------------------------------
/images/image-20230531114811060.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230531114811060.png
--------------------------------------------------------------------------------
/images/image-20230702224006153.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230702224006153.png
--------------------------------------------------------------------------------
/images/image-20230702224040084.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230702224040084.png
--------------------------------------------------------------------------------
/images/image-20230704203814374.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230704203814374.png
--------------------------------------------------------------------------------
/images/image-20230706002351136.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230706002351136.png
--------------------------------------------------------------------------------
/images/image-20230706231238605.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230706231238605.png
--------------------------------------------------------------------------------
/images/image-20230707221251382.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230707221251382.png
--------------------------------------------------------------------------------
/images/image-20230707221904048.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230707221904048.png
--------------------------------------------------------------------------------
/images/image-20230707222414428.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230707222414428.png
--------------------------------------------------------------------------------
/images/image-20230707230357034.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230707230357034.png
--------------------------------------------------------------------------------
/images/image-20230712224427132.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230712224427132.png
--------------------------------------------------------------------------------
/images/image-20230712224654575.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230712224654575.png
--------------------------------------------------------------------------------
/images/image-20230712224758752.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230712224758752.png
--------------------------------------------------------------------------------
/images/image-20230713164436865.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230713164436865.png
--------------------------------------------------------------------------------
/images/image-20230713172611705.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230713172611705.png
--------------------------------------------------------------------------------
/images/image-20230713174303812.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230713174303812.png
--------------------------------------------------------------------------------
/images/image-20230713175843996.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230713175843996.png
--------------------------------------------------------------------------------
/images/image-20230714224309258.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230714224309258.png
--------------------------------------------------------------------------------
/images/image-20230715220315995.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230715220315995.png
--------------------------------------------------------------------------------
/images/image-20230716162205621.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230716162205621.png
--------------------------------------------------------------------------------
/images/image-20230723144125437.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230723144125437.png
--------------------------------------------------------------------------------
/images/image-20230723144137686.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230723144137686.png
--------------------------------------------------------------------------------
/images/image-20230723144901708.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230723144901708.png
--------------------------------------------------------------------------------
/images/image-20230723145117067.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230723145117067.png
--------------------------------------------------------------------------------
/images/image-20230727192100476.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230727192100476.png
--------------------------------------------------------------------------------
/images/image-20230808214706581.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230808214706581.png
--------------------------------------------------------------------------------
/images/image-20230814232203982.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230814232203982.png
--------------------------------------------------------------------------------
/images/image-20230819112844773.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230819112844773.png
--------------------------------------------------------------------------------
/images/image-20230822185247930.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230822185247930.png
--------------------------------------------------------------------------------
/images/image-20230831235036611.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230831235036611.png
--------------------------------------------------------------------------------
/images/image-20230831235206080.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230831235206080.png
--------------------------------------------------------------------------------
/images/image-20230831235326572.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230831235326572.png
--------------------------------------------------------------------------------
/images/image-20230831235617247.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230831235617247.png
--------------------------------------------------------------------------------
/images/image-20230917202951477.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230917202951477.png
--------------------------------------------------------------------------------
/images/image-20230917203005664.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230917203005664.png
--------------------------------------------------------------------------------
/images/image-20230917203147162.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230917203147162.png
--------------------------------------------------------------------------------
/images/image-20230917203152483.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20230917203152483.png
--------------------------------------------------------------------------------
/images/image-20231112233942782.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20231112233942782.png
--------------------------------------------------------------------------------
/images/image-20231127130443086.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/images/image-20231127130443086.png
--------------------------------------------------------------------------------
/linear list(线性表)/ST_RMQ.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 | //例子
5 | const int N=1e6+10;
6 | int f[N][20]; //20是由log2(n+1)+1算出来的
7 | int n,m;
8 |
9 | int query(int l,int r){
10 | // int x=(int)log(r-l+1)/log(2);
11 | int x=(int)log2(r-l+1);
12 | return max(f[l][x],f[r-(1<>n>>m;
18 | for(int i=1;i<=n;++i){
19 | int p;
20 | cin>>p;
21 | f[i][0]=p;
22 | }
23 | //外层循环是遍历列,列不需要遍历到n,而是2的j次方小于等于n
24 | // 因为f[i][j]代表的是从i开始的2的j次方个元素的最值,因此j最大只能取到log2(n)
25 | for(int j=1;(1<>x>>y;
34 | cout<
2 | #include
3 | #include
4 | using namespace std;
5 |
6 | struct Node{
7 | int val; //存储元素值
8 | vectornext; //存储各层数指针的数组
9 | int level; //阶数
10 | };
11 |
12 |
13 | class skiplist{
14 | public:
15 | skiplist(int level):Maxlevel(level){
16 | head= createNode(NULL,Maxlevel);
17 | }
18 | ~skiplist() {
19 | Node* tail=head;
20 | Node* p;
21 | while (tail!= nullptr){
22 | p=tail;
23 | tail=tail->next[0];
24 | delete p;
25 | }
26 | head= nullptr;
27 | };
28 |
29 | Node* find(int data);
30 | void insert(int data);
31 | void del(int data);
32 | void print();
33 |
34 | private:
35 | Node* head;
36 | int Maxlevel;
37 |
38 | Node* createNode(int data,int level){
39 | auto p = new Node;
40 | p->val=data;
41 | p->level=level;
42 | p->next.resize(level,NULL);
43 | return p;
44 | }
45 |
46 | int rand_level(){
47 | int level=1;
48 | while(rand()%2&&level<=Maxlevel){
49 | level++;
50 | }
51 | return level;
52 | }
53 |
54 |
55 | };
56 |
57 | Node *skiplist::find(int data) {
58 | Node* p=head;
59 | for(int i=Maxlevel-1;i>=0;i--){
60 | while (p->next[i]!= nullptr&&p->next[i]->valnext[i];
62 | }
63 | }
64 | if(p->next[0]!= nullptr&&p->next[0]->val==data){
65 | return p->next[0];
66 | }
67 | return nullptr;
68 | }
69 |
70 | void skiplist::insert(int data) {
71 | int level=rand_level();
72 | Node* add= createNode(data,level);
73 | if(head->next[0]== nullptr){
74 | head->next[0]=add;
75 | return;
76 | }
77 | Node* p=head;
78 | Node* prev[level];
79 | for(int i=level-1;i>=0;i--){
80 | while (p->next[i]!= nullptr&&p->next[i]->valnext[i];
82 | }
83 | prev[i]=p;
84 | }
85 | for(int i=0;inext[i]=prev[i]->next[i];
87 | prev[i]->next[i]=add;
88 | }
89 | }
90 |
91 | void skiplist::del(int data) {
92 | Node* p=head;
93 | Node* prev[Maxlevel];
94 | for(int i=Maxlevel-1;i>=0;i--){
95 | while (nullptr!=p->next[i]&&p->next[i]->valnext[i];
97 | }
98 | prev[i]=p;
99 | }
100 | if(p->next[0]!= nullptr&&p->next[0]->val==data){
101 | Node* tail=p->next[0];
102 | for(int i=Maxlevel-1;i>=0;i--){
103 | if(prev[i]->next[i]!= nullptr&&prev[i]->next[i]->val==data)
104 | prev[i]->next[i]=prev[i]->next[i]->next[i];
105 | }
106 | delete tail;
107 | }
108 | }
109 |
110 | void skiplist::print() {
111 | Node* p=head->next[0];
112 | while (p!= nullptr){
113 | cout<val<<" ";
114 | p=p->next[0];
115 | }
116 | cout<val;
130 | sl.print();
131 | system("pause");
132 | return 0;
133 | }
134 |
--------------------------------------------------------------------------------
/linear list(线性表)/circular_list.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | struct CirNode{
6 | int data;
7 | struct CirNode* next;
8 | struct CirNode *prev;
9 | };
10 |
11 | struct CirNode* createNode(int data){
12 | // struct CirNode* p=(struct CirNode*)malloc(sizeof(struct CirNode));
13 | struct CirNode* p=new struct CirNode;
14 | p->data=data;
15 | p->next=NULL;
16 | p->prev=NULL;
17 | return p;
18 | }
19 |
20 | struct CirNode* inserthead(CirNode* head,int data){
21 | struct CirNode* add= createNode(data);
22 | if(head==NULL){
23 | add->next=add;
24 | add->prev=add;
25 | return add;
26 | }
27 | struct CirNode* p=head;
28 | struct CirNode* p1=head->next;
29 | while (p1!=head){
30 | p1=p1->next;
31 | }
32 | head=add;
33 | head->next=p;
34 | p1->next=head;
35 | head->prev=p1;
36 | p->prev=head;
37 | return head;
38 | }
39 |
40 | //尾插法
41 | struct CirNode* insertlast(CirNode* head,int data){
42 | struct CirNode* add= createNode(data);
43 | if(head==NULL){
44 | add->prev=add;
45 | add->next=add;
46 | return add;
47 | }
48 | struct CirNode* p=head;
49 | while(p->next!=head){
50 | p=p->next;
51 | }
52 | p->next=add;
53 | add->prev=p;
54 | add->next=head;
55 | return head;
56 | }
57 |
58 | struct CirNode* del(CirNode* head,int data){
59 | if(head==NULL){
60 | cout<<"链表没有数据"<data==data){
64 | struct CirNode* p=head->next;
65 | p->prev=head->prev;
66 | // free(head);
67 | delete head;
68 | return p;
69 | }
70 | struct CirNode* tail=head;
71 | struct CirNode* p=head->next;
72 | while (p!=head){
73 | if(p->data==data){
74 | tail->next=p->next;
75 | p->next->prev=tail;
76 | // free(p);
77 | delete p;
78 | return head;
79 | }
80 | tail=p;
81 | p=p->next;
82 | }
83 | }
84 |
85 | void printlist(CirNode* head){
86 | if(head==NULL){
87 | cout<<"链表没有数据"<data<<" ";
92 | p=p->next;
93 | } while (p!=head);
94 | cout<i+1后继Ai并称Ai-1前驱Ai,表中的第一个元素为A1,而最后一个元素为AN.
10 |
11 |
12 |
13 |
14 |
15 | ## 简单数组实现表
16 |
17 | **概念**:
18 |
19 | - 表的实现可以通过数组进行实现,而表的插入和删除,就需要对数组元素进行移动,例如插入,如果向第一个位置插入,我们就需要数组元素都向后移动一位,又如删除第一个元素,就需要将第一个元素删掉,数组元素再向前移动一位。
20 |
21 |
22 |
23 | ```c
24 | #include
25 | #define SIZE 100
26 |
27 | struct List{
28 | int elements[SIZE];
29 | int len; //表中元素的长度(即个数)
30 | };
31 |
32 | //创建一个空表对象
33 | struct List* createList(){
34 | struct List *p;
35 | p=malloc(sizeof(struct List));
36 | p->len=0;
37 | return p;
38 | }
39 |
40 | //判断表是否为空
41 | bool isEmpty(struct List* p){
42 | return p->len==0;
43 | }
44 |
45 | //头插法
46 | void inserthead(struct List *p,int x){
47 | if(p->len>=SIZE){
48 | printf("表已满");
49 | return;
50 | }
51 | for(int i=p->len;i>0;i--){
52 | p->elements[i]=p->elements[i-1];
53 | }
54 | p->elements[0]=x;
55 | p->len++;
56 | return;
57 | }
58 |
59 | //尾插法
60 | void insertlast(struct List*p,int x){
61 | if(p->len>=SIZE){
62 | printf("表已满");
63 | return;
64 | }
65 | p->elements[p->len]=x;
66 | p->len++;
67 | return;
68 | }
69 |
70 | //打印表中数据
71 | void printList(struct List *p){
72 | for(int i=0;ilen;i++){
73 | printf("list element is:%d\n",p->elements[i]);
74 | }
75 | }
76 |
77 | //查找指定值,返回索引
78 | int find(struct List *p,int x){
79 | for(int i=0;ilen;i++){
80 | if(p->elements[i]==x){
81 | return i;
82 | }
83 | }
84 | printf("没有找到值为%d的数据\n",x);
85 | return NULL;
86 | }
87 |
88 | //查找表中对应索引的值,返回值
89 | int findkth(struct List *p,int pos){
90 | if(pos>p->len){
91 | printf("不存在索引为%d的数据\n",pos);
92 | return NULL;
93 | }
94 | return p->elements[pos];
95 | }
96 |
97 | //删除
98 | void delete(struct List *p,int x){
99 | for(int i=0;ilen;i++){
100 | if(p->elements[i]==x){
101 | for(int j=i;jlen-1;j--){
102 | p->elements[j]=p->elements[j+1];
103 | }
104 | p->len--;
105 | break;
106 | }
107 | }
108 | }
109 |
110 |
111 | ```
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | ## 链表
122 |
123 | **与简单数组实现的优缺点**:
124 |
125 | - **优点**:简单数组实现表的插入和删除需要花费大量的时间,尤其当数据量大的时候,则程序的耗时将会难以接受,因此为了避免插入和删除的线性开销,我们需要允许表可以不连续存储,否咋表的部分或全部需要整体移动,因此我们将用**链表**进行实现
126 | - **缺点**:在查找数据的时候,链表所耗的时长更多,因为数组可以直接用索引来获取,但是链表需要遍历表连接的数据,直到找到数据为止。
127 |
128 |
129 |
130 | **概念**:
131 |
132 | - **链表**由一系列**不必在内存相连的结构**组成,每一个结构均含有表元素和指向包含该元素后继元的结构的指针,我们称之为*Next指针*。最后一个单元的Next指针指向NULL,NULL是在c中的定义,c中规定为0.
133 |
134 |
135 |
136 | ```c
137 | struct Node{
138 | int data;
139 | struct Node* next;
140 | };
141 |
142 | struct Node *createNode(int data){
143 | struct Node *p=(struct Node* )malloc(sizeof(struct Node));
144 | p->data=data;
145 | p->next=NULL;
146 | return p;
147 | }
148 |
149 | //头插法
150 | struct Node *inserthead(struct Node *head, int data) {
151 | struct Node *add = createNode(data);
152 | if (head == NULL) {
153 | return add;
154 | }
155 | // struct Node *p = head;
156 | // head = add;
157 | // head->next = p;
158 | // return head;
159 | add->next = head;
160 | return add;
161 | }
162 |
163 | //尾插法
164 | struct Node *insert(Node *head,int data){
165 | struct Node *add=createNode(data);
166 | if(head==NULL){
167 | return add;
168 | }
169 | while(head->next!=NULL){
170 | head=head->next;
171 | }
172 | head->next=add;
173 | return head;
174 | }
175 |
176 | struct Node *search(Node *head,int data){
177 | if(head==NULL||head->data==data){
178 | return head;
179 | }
180 | struct Node *p=head;
181 | while(p->next!=NULL){
182 | if(p->data==data){
183 | return p;
184 | }
185 | p=p->next;
186 | }
187 | return NULL;
188 | }
189 |
190 | struct Node *del(Node *head,int data){
191 | if(head==NULL){
192 | return head;
193 | }
194 | if(head->data==data){
195 | struct Node *p=head->next;
196 | free(head);
197 | return p;
198 | }
199 | struct Node *tail=head;
200 | struct Node *p=head->next;
201 | while(p!=NULL){
202 | if(p->data==data){
203 | break;
204 | }
205 | tail=p;
206 | p=p->next;
207 | }
208 | if(p!=NULL&&p->data==data){
209 | tail->next=p->next;
210 | free(p);
211 | }
212 | return head;
213 | }
214 | //清除链表
215 | struct destoty(Node *head){
216 | if(head!=NULL){
217 | destory(head->next);
218 | free(head);
219 | }
220 | }
221 | ```
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 | ## 双向非循环链表
230 |
231 | **作用**:
232 |
233 | - **有时候以倒序扫描链表更方便**,但是为了实现这个就会多出一条附加链的开销,他**增加了空间的需求**,同时使得插入和删除的开销增加一倍,但是**又简化了删除操作**。
234 |
235 | **概念**:
236 |
237 | - **双向非循环链表**就是双向的链表,链表中的前后结点都有指向对方的指针,就是A1的next为A2,但是A2又有指针指向A1.
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 | 代码:
246 |
247 | ```c++
248 | struct doublyNode{
249 | int data;
250 | struct doublyNode* next;
251 | struct doublyNode* prev;
252 | };
253 |
254 | struct doublyNode *createNode(int data){
255 | auto* p=(struct doublyNode*)malloc(sizeof(struct doublyNode));
256 | p->data=data;
257 | p->prev=NULL;
258 | p->next=NULL;
259 | return p;
260 | }
261 |
262 | //头插法
263 | struct doublyNode*inserthead(struct doublyNode* head,int data){
264 | struct doublyNode*add= createNode(data);
265 | if(head==NULL){
266 | return add;
267 | }
268 | struct doublyNode*p=head;
269 | head=add;
270 | head->next=p;
271 | p->prev=head;
272 | return head;
273 | }
274 |
275 | //尾插法
276 | struct doublyNode * insertlast(struct doublyNode* head,int data){
277 | struct doublyNode* add= createNode(data);
278 | if(head==NULL){
279 | return add;
280 | }
281 | struct doublyNode*p=head;
282 | while (p->next!=NULL){
283 | p=p->next;
284 | }
285 | p->next=add;
286 | p->prev=p;
287 | return head;
288 | }
289 |
290 | //删除
291 | doublyNode * del(struct doublyNode* head,int data){
292 | if(head==NULL){
293 | cout<<"链表没有数据"<data==data){
297 | struct doublyNode* p=head->next;
298 | free(head);
299 | return p;
300 | }
301 | struct doublyNode* tail=head;
302 | struct doublyNode* p=head->next;
303 | while (p!=NULL){
304 | if(p->data==data){
305 | tail->next=p->next;
306 | free(p);
307 | return head;
308 | }
309 | tail=p;
310 | p=p->next;
311 | }
312 | }
313 |
314 | void printlist(struct doublyNode* head){
315 | if(head==NULL){
316 | cout<<"链表没有数据"<data<<" ";
321 | p=p->next;
322 | }
323 | cout<
343 |
344 |
345 |
346 |
347 |
348 | 代码:
349 |
350 | ```c++
351 | //单向循环链表
352 | struct CirNode{
353 | int data;
354 | struct CirNode* next;
355 | struct CirNode *prev;
356 | };
357 |
358 | struct CirNode* createNode(int data){
359 | struct CirNode* p=(struct CirNode*)malloc(sizeof(struct CirNode));
360 | p->data=data;
361 | p->next=NULL;
362 | p->prev=NULL;
363 | return p;
364 | }
365 |
366 | struct CirNode* inserthead(CirNode* head,int data){
367 | struct CirNode* add= createNode(data);
368 | if(head==NULL){
369 | add->next=add;
370 | add->prev=add;
371 | return add;
372 | }
373 | struct CirNode* p=head;
374 | struct CirNode* p1=head->next;
375 | while (p1!=head){
376 | p1=p1->next;
377 | }
378 | head=add;
379 | head->next=p;
380 | p1->next=head;
381 | head->prev=p1;
382 | p->prev=head;
383 | return head;
384 | }
385 |
386 | //尾插法
387 | struct CirNode* insertlast(CirNode* head,int data){
388 | struct CirNode* add= createNode(data);
389 | if(head==NULL){
390 | add->prev=add;
391 | add->next=add;
392 | return add;
393 | }
394 | struct CirNode* p=head;
395 | while(p->next!=head){
396 | p=p->next;
397 | }
398 | p->next=add;
399 | add->prev=p;
400 | add->next=head;
401 | return head;
402 | }
403 |
404 | struct CirNode* del(CirNode* head,int data){
405 | if(head==NULL){
406 | cout<<"链表没有数据"<data==data){
410 | struct CirNode* p=head->next;
411 | p->prev=head->prev;
412 | free(head);
413 | return p;
414 | }
415 | struct CirNode* tail=head;
416 | struct CirNode* p=head->next;
417 | while (p!=head){
418 | if(p->data==data){
419 | tail->next=p->next;
420 | p->next->prev=tail;
421 | free(p);
422 | return head;
423 | }
424 | tail=p;
425 | p=p->next;
426 | }
427 | }
428 |
429 | void printlist(CirNode* head){
430 | if(head==NULL){
431 | cout<<"链表没有数据"<data<<" ";
436 | p=p->next;
437 | } while (p!=head);
438 | cout<i+k节点(也就是跳过2i个节点,i为层数)
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 | **随机化算法**:
484 |
485 | - 该算法用于给跳表插入新元素时,进行随机产生k阶节点用于作为新元素值得载体插入在跳表中。
486 | - 虽然是随机的,但是各阶节点的产生是有概率性的,1/2是一阶节点,1/4是2阶节点,大约1/2i的节点是i阶节点。
487 |
488 |
489 |
490 |
491 |
492 | **查找操作**:
493 |
494 | - 首先**在最高级索引上查找最后一个小于当前查找元素的位置**,**然后再跳到次高级索引继续查找,直到跳到最底层为止。**
495 | - 跳表的数据结构大大提高了查找操作,跳表的**查找操作类似于二分查找**。
496 |
497 |
498 |
499 |
500 |
501 | **插入操作**:
502 |
503 | 1. **随机产生阶数,然后根据阶数跟数值创建节点**
504 |
505 | 2. 如果**新创建的表头**,则**直接令表头的第一层索引指针指向新创建的节点**,如果**不是就根据上步产生的阶数创建prev数组用来存储每层要插入节点位置的前继节点,遍历每一层,将prev赋值完**。
506 | 3. 然后**根据阶数遍历,插入到存储到prev的前继节点的下一个位置。**
507 |
508 |
509 |
510 |
511 |
512 | **删除操作**:
513 |
514 | 1. 跟插入操作差不多,**先进行将prev数组赋值**
515 | 2. 然后**遍历每层,将每层的前继节点指向被删除节点的下一个节点**。
516 | 3. **释放被删除节点的空间**。
517 |
518 |
519 |
520 |
521 |
522 | **代码**:
523 |
524 | ```c++
525 | struct Node{
526 | int val; //存储元素值
527 | vectornext; //存储各层数指针的数组
528 | int level; //阶数
529 | };
530 |
531 |
532 | class skiplist{
533 | public:
534 | skiplist(int level):Maxlevel(level){
535 | head= createNode(NULL,Maxlevel);
536 | }
537 | ~skiplist() {
538 | Node* tail=head;
539 | Node* p;
540 | while (tail!= nullptr){
541 | p=tail;
542 | tail=tail->next[0];
543 | delete p;
544 | }
545 | head= nullptr;
546 | };
547 |
548 | Node* find(int data);
549 | void insert(int data);
550 | void del(int data);
551 | void print();
552 |
553 | private:
554 | Node* head;
555 | int Maxlevel;
556 |
557 | Node* createNode(int data,int level){
558 | auto p = new Node;
559 | p->val=data;
560 | p->level=level;
561 | p->next.resize(level,NULL);
562 | return p;
563 | }
564 |
565 | int rand_level(){
566 | int level=1;
567 | while(rand()%2&&level<=Maxlevel){
568 | level++;
569 | }
570 | return level;
571 | }
572 |
573 |
574 | };
575 |
576 | Node *skiplist::find(int data) {
577 | Node* p=head;
578 | for(int i=Maxlevel-1;i>=0;i--){
579 | while (p->next[i]!= nullptr&&p->next[i]->valnext[i];
581 | }
582 | }
583 | if(p->next[0]!= nullptr&&p->next[0]->val==data){
584 | return p->next[0];
585 | }
586 | return nullptr;
587 | }
588 |
589 | void skiplist::insert(int data) {
590 | int level=rand_level();
591 | Node* add= createNode(data,level);
592 | if(head->next[0]== nullptr){
593 | head->next[0]=add;
594 | return;
595 | }
596 | Node* p=head;
597 | Node* prev[level];
598 | for(int i=level-1;i>=0;i--){
599 | while (p->next[i]!= nullptr&&p->next[i]->valnext[i];
601 | }
602 | prev[i]=p;
603 | }
604 | for(int i=0;inext[i]=prev[i]->next[i];
606 | prev[i]->next[i]=add;
607 | }
608 | }
609 |
610 | void skiplist::del(int data) {
611 | Node* p=head;
612 | Node* prev[Maxlevel];
613 | for(int i=Maxlevel-1;i>=0;i--){
614 | while (nullptr!=p->next[i]&&p->next[i]->valnext[i];
616 | }
617 | prev[i]=p;
618 | }
619 | if(p->next[0]!= nullptr&&p->next[0]->val==data){
620 | Node* tail=p->next[0];
621 | for(int i=Maxlevel-1;i>=0;i--){
622 | if(prev[i]->next[i]!= nullptr&&prev[i]->next[i]->val==data)
623 | prev[i]->next[i]=prev[i]->next[i]->next[i];
624 | }
625 | delete tail;
626 | }
627 | }
628 |
629 | void skiplist::print() {
630 | Node* p=head->next[0];
631 | while (p!= nullptr){
632 | cout<val<<" ";
633 | p=p->next[0];
634 | }
635 | cout<j个元素的最值**
661 | 2. 将第i个元素开始的2j个元素**分成长度相等的两部分,每部分的长度为2j-1**
662 | 3. `状态转移方程`就为:**f[i\][j]=max(f[i\][j-1],f[i+2j-1\][j-1])**,即两部分的最大值
663 | 4. `边界条件`:**f[i\][0]=a[i]**
664 | 5. 要询问区间[L,R]的最大值,因区间[L,R]的长度为R-L+1,**求出log2(R-L+1)的值,设为x**
665 | 6. 因此区间[L,R]就可以分为[L,L+2x-1]和[R-2x+1,R]两个部分,根据状态转移方程可以得出`区间[L,R]的最大值`:**RMQ(L,R)=max(f[L\][x],f[R-2x+1\][x])**
666 | 7. **2x可以用移位运算1<
697 | #include
698 | using namespace std;
699 | //例子
700 | const int N=1e6+10;
701 | int f[N][20]; //20是由log2(n)+1算出来的
702 | int n,m;
703 |
704 | int query(int l,int r){
705 | // int x=(int)log(r-l+1)/log(2);
706 | int x=(int)log2(r-l+1);
707 | return max(f[l][x],f[r-(1<>n>>m;
713 | for(int i=1;i<=n;++i){
714 | int p;
715 | cin>>p;
716 | f[i][0]=p;
717 | }
718 | //外层循环是遍历列,列不需要遍历到n,而是2的j次方小于等于n
719 | // 因为f[i][j]代表的是从i开始的2的j次方个元素的最值,因此j最大只能取到log2(n)
720 | for(int j=1;(1<>x>>y;
729 | cout<
748 |
749 |
750 |
751 | ```c++
752 | #include
753 | #include
754 | #include
755 | using namespace std;
756 |
757 |
758 | int n, k;
759 |
760 | //ST算法
761 | int query(int l, int r, vector> &f) {
762 | int x = (int)log2(r - l + 1);
763 | return min(f[l][x], f[r - (1 << x) + 1][x]);
764 | }
765 |
766 | int main() {
767 | cin >> n ;
768 | int logn = log2(n) + 1;
769 | vector>f(n + 1, vector(logn));
770 |
771 | for (int i = 1; i <= n; ++i) {
772 | cin >> f[i][0];
773 | }
774 |
775 | for (int j = 1; (1 << j) <= n; ++j) {
776 | for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
777 | f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
778 | }
779 | }
780 | cin >> k;
781 | for (int i = 1; i <= n; ++i) {
782 | int l = max(1, i - k);
783 | int r = min(n, i + k);
784 | cout << query(l, r, f) << " ";
785 | }
786 | cout << endl;
787 | return 0;
788 | }
789 | ```
790 |
791 |
792 |
793 |
--------------------------------------------------------------------------------
/linear list(线性表)/list.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/linear list(线性表)/list.cpp
--------------------------------------------------------------------------------
/queue(队列)/queue(队列).md:
--------------------------------------------------------------------------------
1 | # 队列(queue)
2 |
3 | **概念**:
4 |
5 | - **队列**也是一种线性表,使用队列时插入在一端进行而删除则在另一端进行,队列的基本操作是**入队**,它是在**表的末端**(也叫做**队尾**)插入一个元素,**出队**,它是删除在**表的开头(****队头**)的元素。
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | **数组实现**:
22 |
23 | ```c++
24 | //数组实现
25 | class queue{
26 | public:
27 | //入队(向数组末尾插入数据)
28 | void Push(int data){
29 | head.push_back(data);
30 | }
31 |
32 | //出队(将数组第一个元素删除)
33 | void Pop(){
34 | if(head.empty()){
35 | cout<<"队列中没有数据!"<head;
85 | };
86 | ```
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | **链表实现:**
95 |
96 | ```c++
97 | //链表实现
98 | struct Queue{
99 | int data;
100 | Queue* next;
101 | };
102 |
103 | Queue* createNode(int data){
104 | auto p=new Queue;
105 | p->data=data;
106 | p->next=NULL;
107 | return p;
108 | }
109 |
110 | //入队
111 | void push(Queue* &head,int data){
112 | Queue* add= createNode(data);
113 | if (head==NULL){
114 | head=add;
115 | }else{
116 | Queue* p=head;
117 | while (p->next!=NULL){
118 | p=p->next;
119 | }
120 | p->next=add;
121 | }
122 | }
123 |
124 | //出队
125 | void pop(Queue* &head){
126 | if(head==NULL){
127 | cout<<"队列中没有元素"<next;
132 | delete p;
133 | }
134 |
135 | //获取队首元素
136 | int front(Queue* &head){
137 | if(head==NULL){
138 | cout<<"队列中没有元素"<data;
142 | }
143 |
144 | //打印队列
145 | void print(Queue* &head){
146 | if(head==NULL){
147 | cout<<"队列中没有元素"<data<<" ";
153 | p=p->next;
154 | }
155 | cout<next;
165 | while (head!=NULL){
166 | delete head;
167 | head=tail;
168 | if(tail!=NULL)
169 | tail=tail->next;
170 | else
171 | return;
172 | }
173 | }
174 | ```
175 |
176 |
--------------------------------------------------------------------------------
/queue(队列)/queue.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoonforDream/Data-Structure-and-Algorithms/43f1a1cf9f6e0f37f72442968743790ba3287fd3/queue(队列)/queue.cpp
--------------------------------------------------------------------------------
/stack(栈)/Reverse_Polan.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | bool flag(char a,char b){
8 | int a1,b1;
9 | if(a=='+'||a=='-'){
10 | a1=1;
11 | }else if(a=='*'||a=='/'){
12 | a1=2;
13 | }else if(a=='('||a==')'){
14 | a1=3;
15 | }
16 | if(b=='+'||b=='-'){
17 | b1=1;
18 | }else if(b=='*'||b=='/'){
19 | b1=2;
20 | }else if(b=='('||b==')'){
21 | b1=3;
22 | }
23 | return a1>=b1;
24 | }
25 |
26 | vector reversePolan(char *an,int len){
27 | stacks;
28 | vectorv;
29 | int cnt=0;
30 | for(int i=0;i - 如果栈的大小已知且固定,或者对随机访问元素效率有较高要求,使用**数组**实现栈可能更合适。
17 | > - 如果栈的大小不确定,或者插入和删除操作频繁且在栈顶之外发生,使用**链表**实现栈可能更有优势。
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | **链表实现代码**:
28 |
29 | ```c++
30 | struct Node{
31 | int data;
32 | Node *next;
33 | };
34 | typedef Node* Stack;
35 |
36 | Stack createStack(int data){
37 | struct Node* p=new struct Node;
38 | p->data=data;
39 | p->next=NULL;
40 | return p;
41 | }
42 |
43 | //进栈
44 | void Push(Stack &head,int data){
45 | Stack add= createStack(data);
46 | if(head==NULL){
47 | head=add;
48 | }else{
49 | Node* p=head;
50 | add->next=p;
51 | head=add;
52 | }
53 | }
54 |
55 | //出栈
56 | void Pop(Stack &head){
57 | if(head==NULL){
58 | cout<<"栈中没有数据"<next;
63 | delete p;
64 | }
65 |
66 | //获取栈顶元素
67 | int top(Stack head){
68 | return head->data;
69 | }
70 |
71 |
72 | //打印栈
73 | void printStack(Stack head){
74 | if(head==NULL){
75 | cout<<"栈中没有数据"<data<<" ";
81 | p=p->next;
82 | }
83 | cout<data&&p->next==NULL){
91 | cnt=1;
92 | } else{
93 | while (p!=NULL){
94 | cnt++;
95 | p=p->next;
96 | }
97 | }
98 | return cnt;
99 | }
100 |
101 | //判断栈是否为空
102 | bool empty(Stack head){
103 | if (head!=NULL){
104 | return false;
105 | }else{
106 | return true;
107 | }
108 | }
109 |
110 | //清空栈
111 | void destroy(Stack &head){
112 | if(head==NULL){
113 | cout<<"栈中没有数据"<next;
117 | while (head!=NULL){
118 | delete head;
119 | head=tail;
120 | if(tail!=NULL)
121 | tail=tail->next;
122 | else
123 | return;
124 | }
125 | }
126 | ```
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | **数组实现代码:**
137 |
138 | ```c++
139 | class stack{
140 | public:
141 | //入栈
142 | void Push(int data){
143 | head.push_back(data);
144 | }
145 |
146 | //出栈
147 | void Pop(){
148 | if(head.empty()){
149 | cout<<"栈中没有数据!"<::const_iterator it=head.end()-1;it>=head.begin();it--){
171 | cout<<*it<<" ";
172 | }
173 | cout<head;
197 | };
198 | ```
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 | ## 逆波兰转换式
211 |
212 | **概念**:
213 |
214 | - 一种**后缀表达式**,例如a+b+c*d,转换成逆波兰表达式就为:a b + c d * +,然后我们将逆波兰表达式压入栈中(*将元素压入栈中遇到运算符号就将栈中的两个元素进行出栈在进行运算,运算完后再压入栈中,重复操作就能得到逆波兰表达式的结果*),逆波兰表达式中没有括号!
215 |
216 | - 转换成逆波兰表达式,需要一个空栈跟一个临时输出区(但不直接输出),将**运算元素放进临时输出区**,将**运算符号压入栈**中。
217 |
218 | > - 如果运算符的优先级大于上一个运算符,就进行入栈。
219 | > - 如果运算符的优先级小于等于上一个运算符,就将前面的运算符出栈放在临时输出区,再将该运算符入栈。
220 | > - 如果栈中有左括号,后面入栈的运算符不是右括号的话,左括号就不出栈,而是继续重复上两个规则,直到右括号出现就将左括号出栈,但括号不放入临时输出区
221 | > - 当运算元素都放入临时输出区时,栈区还有运算符就直接出栈放入临时存放区,最终将临时存放区按顺序输出出来就是转换的逆波兰表达式
222 |
223 |
224 |
225 | **代码**:
226 |
227 | ```c++
228 | bool flag(char a,char b){
229 | int a1,b1;
230 | if(a=='+'||a=='-'){
231 | a1=1;
232 | }else if(a=='*'||a=='/'){
233 | a1=2;
234 | }else if(a=='('||a==')'){
235 | a1=3;
236 | }
237 | if(b=='+'||b=='-'){
238 | b1=1;
239 | }else if(b=='*'||b=='/'){
240 | b1=2;
241 | }else if(b=='('||b==')'){
242 | b1=3;
243 | }
244 | return a1>=b1;
245 | }
246 |
247 | vector reversePolan(char *an,int len){
248 | stacks;
249 | vectorv;
250 | int cnt=0;
251 | for(int i=0;i 1. 寻找左侧第一个比当前元素大的元素
331 | > 2. 寻找左侧第一个比当前元素小的元素
332 | > 3. 寻找右侧第一个比当前元素大的元素
333 | > 4. 寻找右侧第一个比当前元素小的元素
334 |
335 |
336 |
337 |
338 |
339 | **各问题解决做法**:
340 |
341 | `总结`:
342 |
343 | - 查找**比当前大的元素用单调递增栈**,查找**比当前小的元素用单调递减栈**
344 | - 从**左侧**查找就**看插入栈时的栈顶元素**,从**右侧**查找就**看弹出栈时即将插入的元素**
345 |
346 | 1. `寻找左侧第一个比当前元素大的元素`:
347 |
348 | > - 构造一个**单调递增栈(从栈顶到栈底)**
349 | > - **从左到右遍历元素**
350 | > - 如果**当前元素大于栈顶元素**,则将其**加入**(也就是将栈里面小于当前元素的都弹出再插入);
351 | > - 如果**小于**,则**当前栈顶元素就是当前遍历的元素左侧第一个比它大的元素**
352 | > - 如果插入时的**栈为空**,则**说明左侧不存在比当前元素大的元素**
353 |
354 | 2. `寻找左侧第一个比当前元素小的元素`:
355 |
356 | > - 构造一个**单调递减栈(从栈顶到栈底)**
357 | > - **从左到右遍历元素**
358 | > - 如果当前元素**小于**栈顶元素,就**加入**栈中
359 | > - 如果**大于**,则**当前栈顶元素就是当前遍历元素左侧第一个比它小的元素**
360 | > - 如果插入时的**栈为空**,则**说明左侧不存在比当前元素小的元素**
361 |
362 | 3. `寻找右侧第一比当前元素大的元素`:
363 |
364 | > - 构造一个**单调递增栈(从栈顶到栈底)**
365 | > - **从左到右遍历元素**
366 | > - 如果**当前遍历元素大于当前栈底元素**,则**当前栈顶元素的右侧第一个比它大的元素就是当前遍历元素**
367 | > - 如果**小于**,则将其**加入**栈中
368 | > - 如果在**栈中的元素没有被弹出**,说明栈中**剩下的元素没有右侧比它大的元素**
369 |
370 | 4. `寻找右侧第一个比当前元素小的元素`:
371 |
372 | > - 构造一个**单调递减栈(从栈顶到栈底)**
373 | > - **从左到右遍历元素**
374 | > - 如果**当前遍历元素小于当前栈顶元素**,则**当前栈顶元素的右侧第一个比它小的元素就是当前遍历元素**
375 | > - 如果**大于**,则**加入**栈中
376 | > - 如果在**栈中的元素没有被弹出**,说明栈中**剩下的元素没有右侧比它小的元素**
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 | **模板代码**:
385 |
386 | 1. `单调递增栈`
387 |
388 | ```c++
389 | int main(){
390 | stackst;
391 | for(int i=0;i