數據結構:鏈表

在這裏給出數組實現單鏈表和雙鏈表以及指針實現單鏈表和雙鏈表的例子,爲之後更爲複雜的數據結構實現打基礎。node

首先介紹一下使用數組來實現鏈表的原理ios

int node[maxn];
int cur=0;
int Next[maxn];
int tot=0;

node數組是用來保存全部的節點的取值的,這裏面的節點是程序生成的流水節點,其真正有沒有出如今鏈表中是沒有任何關係的數組

cur用來指示當前在node數組中的哪個位置,是一個位置變量數據結構

Next數組用來存node數組中下標位置的節點所鏈接的下一個元素在node數組中的下標,是鏈表的核心函數

tot用來記錄當前鏈表中有多少個節點測試

先是單鏈表spa

接下來咱們給出其中最主要的函數的定義,insert_back函數設計

void insert_back(int a,int s)
{
    cur++;
    node[cur]=s;
    Next[cur]=Next[a];
    Next[a]=cur;
}

這個函數的用途是在鏈表a位置的元素後面插入一個新的值爲s的節點指針

首先第一步是把新節點賦值以後加入到node數組的尾部code

接下來要作的就是插入了,讓新節點的下一個元素指向a節點以前指向的元素

而後讓a節點的下一個元素指向新節點

下面給出單鏈表數組實現的完整程序

 1 #include<iostream>
 2 using namespace std;
 3 const int maxn=1005; 
 4 int n;
 5 int node[maxn];
 6 int cur=0;
 7 int Next[maxn];
 8 int tot=0;
 9 void insert(int a,int b,int s)
10 {
11     cur++;
12     node[cur]=s;
13     Next[a]=cur;
14     Next[cur]=b;
15 }
16 void insert_back(int a,int s)
17 {
18     cur++;
19     node[cur]=s;
20     Next[cur]=Next[a];
21     Next[a]=cur;
22 }
23 void insert_front(int b,int s)
24 {
25     cur++;
26     node[cur]=s;
27     Next[cur]=b;
28     int a;
29     for(int i=1;i<=cur;i++)
30     {
31         if(Next[i]==b)
32         {
33             a=i;
34             break;
35         } 
36     }
37     Next[a]=cur;
38 }
39 void _delete(int a,int b)
40 {
41     Next[a]=b;
42 }
43 void delete_back(int a)
44 {
45     Next[a]=Next[Next[a]];
46 }
47 void delete_front(int b)
48 {
49     int s;
50     for(int i=1;i<=cur;i++)
51     {
52         if(Next[i]==b)
53         {
54             s=i;
55             break;
56         }
57     }
58     int a;
59     for(int i=1;i<=cur;i++)
60     {
61         if(Next[i]==s)
62         {
63             a=i;
64             break;
65         }
66     }
67     Next[a]=b;
68 }
69 int main()
70 {
71     cin>>n;
72     int tmp;
73     cin>>tmp;
74     insert_back(0,tmp);
75     tot++;
76     for(int i=1;i<n;i++)
77     {
78         cin>>tmp;
79         insert_back(i,tmp);
80         tot++;
81     }
82     tmp=Next[0];
83     while(tmp)
84     {
85         cout<<node[tmp]<<" ";
86         tmp=Next[tmp];
87     }
88     return 0; 
89 }

而後咱們介紹雙鏈表的數組實現

int node[maxn]; 
int Prev[maxn];
int Next[maxn];
int cur;
int tot=0;

在原來的基礎上新加入了一個數組,用來表示下標位置節點的前一個節點在node數組中的下標

而後咱們仍是以insert_back函數爲例子

void insert_back(int a,int s)
{
    cur++;
    node[cur]=s;
    Prev[Next[a]]=cur;
    Next[cur]=Next[a];
    
    Prev[cur]=a;
    Next[a]=cur;
}

首先將新節點放入node數組中

讓a節點的下一個節點的前驅節點指向新節點

讓a節點的下一個節點成爲新節點的後繼

讓新節點的前驅節點指向a節點

讓a節點的後繼節點指向新節點

下面給出完整的雙鏈表的數組實現程序

 1 #include<iostream>
 2 using namespace std;
 3 const int maxn=1005;
 4 int n;
 5 int node[maxn]; 
 6 int Prev[maxn];
 7 int Next[maxn];
 8 int cur;
 9 int tot=0;
10 void insert(int a,int b,int s)
11 {
12     cur++;
13     node[cur]=s;
14     Next[a]=cur;
15     Prev[cur]=a;
16     
17     Next[cur]=b;
18     Prev[b]=cur;
19 }
20 void insert_back(int a,int s)
21 {
22     cur++;
23     node[cur]=s;
24     Prev[Next[a]]=cur;
25     Next[cur]=Next[a];
26     
27     Prev[cur]=a;
28     Next[a]=cur;
29 }
30 void insert_front(int b,int s)
31 {
32     cur++;
33     node[cur]=s;
34     Next[Prev[b]]=cur;
35     Prev[cur]=Prev[b];
36     
37     Next[cur]=b;
38     Prev[b]=cur; 
39 }
40 void _delete(int a,int b)
41 {
42     Prev[b]=a;
43     Next[a]=b;
44 }
45 void delete_back(int a)
46 {
47     Prev[Next[Next[a]]]=a;
48     Next[a]=Next[Next[a]];
49 }
50 void delete_front(int b)
51 {
52     Next[Prev[Prev[b]]]=b;
53     Prev[b]=Prev[Prev[b]];
54 }
55 int main()
56 {
57     cin>>n;
58     int tmp;
59     cin>>tmp;
60     insert_back(0,tmp);
61     tot++;
62     for(int i=1;i<n;i++)
63     {
64         cin>>tmp;
65         insert_back(i,tmp);
66         tot++;
67     }
68     tmp=Next[0];
69     while(tmp)
70     {
71         cout<<node[tmp]<<" ";
72         tmp=Next[tmp];
73     }
74     return 0; 
75 }

以後咱們要介紹的是鏈表的指針實現

在程序設計競賽中不建議使用這種方式,由於在邊界處理時每每會訪問無效內存

程序競賽中的鏈表,應統一使用數組形式,而對於樹形結構,具體問題具體分析,怎麼方便怎麼來

首先是使用指針實現鏈表的一些注意項

int n;
struct Node
{
    int Data;
    Node *next;
};
Node *head,*rear;

這裏節點被封裝成告終構體看起來舒服一些

next裏存的是下一個節點的地址

head永遠指向鏈表中的第一個元素,這樣方便進行操做

rear是當前的操做項,至關於位置變量

而後仍是以insert_back函數爲例

void insert_back(Node* a,int s)
{
    Node *tmp=new Node();
    tmp->Data=s;
    tmp->next=a->next;
    a->next=tmp;
}

這裏的邏輯和以前的數組實現是徹底一致的

下面給出單鏈表的指針實現的完整代碼

 1 #include<iostream>
 2 using namespace std;
 3 int n;
 4 struct Node
 5 {
 6     int Data;
 7     Node *next;
 8 };
 9 Node *head,*rear;
10 void insert(Node* a,Node* b,int s)
11 {
12     Node *tmp=new Node();
13     tmp->Data=s;
14     a->next=tmp;
15     tmp->next=b;
16 }
17 void insert_back(Node* a,int s)
18 {
19     Node *tmp=new Node();
20     tmp->Data=s;
21     tmp->next=a->next;
22     a->next=tmp;
23 }
24 void insert_front(Node* b,int s)
25 {
26     Node *tmp=new Node();
27     tmp->next=b;
28     Node *a=head;
29     while(a!=NULL)
30     {
31         if(a->next==b)
32             break;
33         a=a->next;
34     }
35     a->next=tmp;
36 }
37 void _delete(Node* a,Node* b)
38 {
39     delete a->next;
40     a->next=b;
41 }
42 void delete_back(Node* a)
43 {
44     Node *tmp=a->next;
45     a->next=a->next->next;
46     delete tmp;
47 }
48 void delete_front(Node* b)
49 {
50     Node *tmp=head;
51     while(tmp!=NULL)
52     {
53         if(tmp->next==b)
54             break;
55         tmp=tmp->next;
56     }
57     Node *a=head;
58     while(a!=NULL)
59     {
60         if(a->next==tmp)
61             break;
62         a=a->next;
63     }
64     a->next=b;
65     delete tmp;
66 }
67 int main()
68 {
69     cin>>n;
70     head=new Node();
71     int tmp;
72     cin>>tmp;
73     rear=new Node();
74     rear->Data=tmp;
75     head->next=rear;
76     for(int i=1;i<n;i++)
77     {
78         cin>>tmp;
79         insert_back(rear,tmp);
80         rear=rear->next;
81     }
82     rear=head->next;
83     while(rear!=NULL)
84     {
85         cout<<rear->Data<<" ";
86         rear=rear->next;
87     }
88     return 0;
89 }

接下來咱們介紹雙向鏈表的指針實現

首先仍是給出定義項

int n;
struct Node
{
    int Data;
    Node *prev,*next;
};

區別就是增長了一個prev用來存前驅節點的地址

而後咱們給出insert_back函數的定義

void insert_back(Node* a,int s)
{
    Node *tmp=new Node();
    tmp->Data=s;
    
    if(a->next!=NULL)
        a->next->prev=tmp;
    tmp->next=a->next;
    
    tmp->prev=a;
    a->next=tmp;
}

這裏的邏輯和以前數組實現基本一致,可是要注意一點那就是必定要考慮好邊界狀況,在這裏就是往鏈表尾部插入的狀況

若是直接是a->next->prev,若是a->next爲空,就是訪問無效內存,直接會運行錯誤

因此要加入一個特判

不僅在這個地方,在其餘的地方也可能出現相似的狀況,因此除非有必要,建議不要使用指針形式的鏈表

下面給出雙向鏈表的指針實現的完整代碼

 1 #include<iostream>
 2 using namespace std;
 3 int n;
 4 struct Node
 5 {
 6     int Data;
 7     Node *prev,*next;
 8 };
 9 Node *head,*rear;
10 void insert(Node* a,Node* b,int s)
11 {
12     Node *tmp=new Node();
13     tmp->Data=s;
14     
15     a->next=tmp;
16     tmp->prev=a;
17     
18     tmp->next=b;
19     b->prev=tmp;
20 }
21 void insert_back(Node* a,int s)
22 {
23     Node *tmp=new Node();
24     tmp->Data=s;
25     
26     if(a->next!=NULL)
27         a->next->prev=tmp;
28     tmp->next=a->next;
29     
30     tmp->prev=a;
31     a->next=tmp;
32 }
33 void insert_front(Node* b,int s)
34 {
35     Node *tmp=new Node();
36     tmp->next=b;
37     
38     b->prev->next=tmp;
39     tmp->prev=b->prev;
40     
41     tmp->next=b;
42     b->prev=tmp;
43 }
44 void _delete(Node* a,Node* b)
45 {
46     Node *tmp=a->next;
47     a->next=b;
48     b->prev=a;
49     
50     delete tmp;
51 }
52 void delete_back(Node* a)
53 {
54     Node *tmp=a->next;
55     
56     tmp->next->prev=a;
57     a->next=tmp->next;
58     
59     delete tmp;
60 }
61 void delete_front(Node* b)
62 {
63     Node *tmp=b->prev;
64     
65     tmp->prev->next=b;
66     b->prev=tmp->prev;
67     
68     delete tmp;
69 }
70 int main()
71 {
72     cin>>n;
73     head=new Node();
74     int tmp;
75     cin>>tmp;
76     rear=new Node();
77     rear->Data=tmp;
78     head->next=rear;
79     rear->prev=head; 
80     for(int i=1;i<n;i++)
81     {
82         cin>>tmp;
83         insert_back(rear,tmp);
84         rear=rear->next;
85     }
86     rear=head->next;
87     while(rear!=NULL)
88     {
89         cout<<rear->Data<<" ";
90         rear=rear->next;
91     }
92     return 0;
93 }

全部的程序只測試了一個函數,別的函數實現僅供參考,若有錯誤歡迎讀者指正。

相關文章
相關標籤/搜索