1. 程式人生 > 實用技巧 >基本資料結構

基本資料結構

基本資料結構


連結串列

陣列與連結串列的不同之處
陣列:支援隨機訪問,不支援在任意位置插入或刪除元素
連結串列:支援在隨機位置插入或刪除,但只能按順序訪問
用struct來表示連結串列的節點,為了避免在左右兩端或者在空連結串列中訪問越界,就新建head和tail節點來表示鏈頭和鏈尾,在這兩個幾點之間儲存實際節點。(以此來減少對於邊界的判斷)
以下是雙鏈表的程式碼實現

定義

1 struct Node{
2     int value;
3     int prev,next;
4 }node[SIZE];
5 int head,tail,tot;

建表

1 void initialize(){
2 tot=2; 3 head=1,tail=2; 4 node[head].next=tail; 5 node[tail].prev=head; 6 }

在節點x後插入包含數值v的新節點

1 void insert(int x,int v){
2     xx=tot++;
3     node[xx].value=v;//v是xx的值 
4     node[node[x].next].prev=xx;//x後面的那個數的前面應該是xx 
5     node[xx].next=node[x].next;//xx的後邊應該是x的後面 
6     node[x].next=xx;//
x的後面一個是xx 7 node[xx].prev=x;//xx的前面是x 8 }

刪除節點x

1 void remove(int x){
2     node[node[x].prev].next=node[x].next;
3     node[node[x].next].prev=node[x].prev;
4 } 

清空連結串列

1 void clear(){
2     memset(node,0,sizeof(node));
3     head=tail=tot=0;
4 }

後進先出

1 int stack[N], top=0;//top表示棧頂 
2 void
push(int a){stack[top++]=a;}//入棧 3 int pop(){return stack[--top];}//出棧 4 bool empty(){return top<0;}//判斷棧是否是空棧

佇列

先進先出

1 int queue[N],front=0,rear=0;//front隊首元素,rear隊尾元素右側 
2 void push(int a){queue[rear++]=a;}
3 int pop(){return queue[front++];}
4 bool empty(){return front==rear;}

單調佇列

啊啊啊啊,終於學了呢,之前dp的坑也可以填了呢。即是保證它是一個單調遞增或遞減的佇列,若檢測到讀入的這個數比它佇列前面的那個數生存能力強,就把前面的數從隊尾擠掉,自己填進去。若比前數生存能力弱,就可以把這個數push進隊尾,畢竟它的出現時間較晚。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e6+10;
 4 int a[N],n,m,f,i,j,s_min[N],s_max[N];
 5 deque<int> x,y;//x小y大 
 6 int main(){
 7     cin>>n>>m;
 8     for(int i=1;i<=n;i++)cin>>a[i];
 9     x.push_front(1);
10     y.push_front(1);
11     s_min[1]=1;
12     s_max[1]=1;
13     m--;
14     for(int i=2;i<=n;i++){
15         while (x.size() && x.front()+m<i)
16             x.pop_front();
17         while (y.size() && y.front()+m<i)
18             y.pop_front();
19 
20         while (x.size() && a[x.back()]>=a[i])
21             x.pop_back();
22         while (y.size() && a[y.back()]<=a[i])
23             y.pop_back();
24             x.push_back(i);
25             y.push_back(i);
26 
27         s_min[i]=x.front();
28         s_max[i]=y.front();
29     }
30     for(int i=m+1;i<=n;i++)
31         cout<<a[s_min[i]]<<" ";
32     cout<<endl;
33     for(int i=m+1;i<=n;i++)
34         cout<<a[s_max[i]]<<" ";
35     return 0;
36 }


二叉樹

用連結串列儲存二叉樹,lson表示左兒子,rson表示右兒子。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,flag[100009],nn;
 4 struct Node{
 5     int num,lson,rson;
 6 }node[100009];
 7 int tot=0;
 8 void qdfs(int x){//前序遍歷 
 9     if(x==0) return;
10     cout<<x<<" ";
11     qdfs(node[x].lson);
12     qdfs(node[x].rson);
13 }
14 void z(int x){//中序遍歷 
15     if(x==0) return;
16     z(node[x].lson);
17     cout<<x<<" ";
18     z(node[x].rson);
19 }
20 void h(int x){//後序遍歷 
21     if(x==0) return;
22     h(node[x].lson);
23     h(node[x].rson);
24     cout<<x<<" ";
25 }
26 int main(){
27     cin>>n;
28     for(int i=1;i<=n;i++){
29         int f,l,r;
30         cin>>f>>l>>r;
31         node[f].lson=l;
32         node[f].rson=r;
33         flag[l]=1,flag[r]=1;
34     }//二叉樹儲存
35     for(int i=1;i<=n;i++) if(flag[i]==0) nn=i;//尋找根節點
36     qdfs(nn);
37     cout<<endl;z(nn);cout<<endl;h(nn);
38     return 0;
39 } 

還有一種神奇的(當然也有點慢)做法(只針對前序遍歷

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,le[27],ri[27];
 4 char f;
 5 void dfs(int x){
 6     cout<<char(x+'a');
 7     if(le[x]!=-1) dfs(le[x]);
 8     if(ri[x]!=-1) dfs(ri[x]);
 9 }
10 int main(){
11     cin>>n;
12     for(int i=1;i<=n;i++){
13         char x,y,z;
14         cin>>x>>y>>z;
15         if(i==1) f=x;
16         if(y=='*') le[x-'a']=-1;
17         else le[x-'a']=y-'a';
18         if(z=='*') ri[x-'a']=-1;
19         else ri[x-'a']=z-'a';
20     }
21     dfs(f-'a');
22     return 0;
23 }

並查集

這就是“附庸的附庸依舊是我的附庸”bushi

1 for(int i=1;i<=n;i++) fa[i]=i;//初始化 
2 int get(int x){//找最大統領 
3     if(x==fa[x]) return x;
4     return fa[x]=get(fa[x]);
5 }
6 void merge(int x,int y){//合併 
7     fa[get(x)]=get(y);
8 }

貼一道

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int size[30001],d[30001],fa[30001];
 4 int get(int x){
 5     if(x==fa[x]) return x;
 6     int root=get(fa[x]);
 7     d[x]+=d[fa[x]];
 8     return fa[x]=root;
 9 }
10 void merge(int x,int y){
11     x=get(x),y=get(y);
12     fa[x]=y,d[x]=size[y];
13     size[y]+=size[x];
14 }
15 int main(){
16     for(int i=1;i<=30001;i++){
17         size[i]=1;
18         fa[i]=i;
19     }
20     int t;
21     cin>>t;
22     for(int i=1;i<=t;i++){
23         char a;
24         int x,y;
25         cin>>a>>x>>y;
26         if(a=='M') merge(x,y);
27         else{
28             if(get(x)!=get(y)) cout<<-1<<endl;
29             else{
30                 if(d[x]>d[y]) cout<<d[x]-d[y]-1<<endl;
31                 else cout<<d[y]-d[x]-1<<endl;
32             }
33         }
34     }
35     return 0;
36 }

後記:期待今晚的可樂(雖然是無糖的,但是還是很喜歡的呢 ps.沒有糖就沒有靈魂了