线性表 链表

计算机中的三大结构:

  • 线形结构  不分叉
  • 树形结构
  • 图形结构

直接前驱、该元素、直接后继

线性表存储

顺序表存储  优点: 快速访问

数组

链式存储  优点:大量删除、更新操作

链表

typedef将结构体等价于 类型名Lnode,指针Linklist

typedef struct Lnode{
  ElemType data;
  struct Lnode *next;   
}Lnode, *Linklist;

如果不这样写就要加上关键字struct来声明变量。

分配变量返回的是指针  s = new Lnode,则s是指针 

链表的两种方式:

  • 头结点
  • 头指针

链表建立:

  • 头插法 逆序建表   有头指针   没有标记的一端先修改,无标记的后修改。 两者都有标记修改哪一个无所谓。 指针只要一断,就找不到了。
  • 尾插法 正序建表   有尾指针

头指针不可以随意改动

 STL List链表是双向链表

代码风格更加偏向工程化 

 

1、单链表操作

  1 #include <iostream>
  2 #include <string>
  3 #include <iomanip>
  4 #include <stdlib.h>
  5 
  6 using namespace std;
  7 
  8 typedef struct LNode{  // LNode为结构体的名字
  9     int data;  // 结点的数据域
 10     struct LNode *next;  // 结点的指针域
 11 }LNode, *LinkList;  // LinkList为指向结构体LNode的指针类型
 12 
 13 /*
 14  typedfs起别名的意思,给整个结构体起了个别名LNode, 指向结构体的指针*LinkList。
 15  */
 16 
 17 bool InitList_L(LinkList &L){  // 构造一个空的单链表L
 18     L = new LNode;  // 生成新节点作为头结点,用头指针L指向头结点
 19     /* 每次用new分配空间总会返回一个地址 */
 20     if(!L)
 21         return false;  // 生成节点失败
 22     L->next = NULL;  // 头结点的指针置为空
 23     return true;
 24 }
 25 
 26 void CreateList_H(LinkList &L){  // 头插法建立单链表  逆序
 27     // 输入n个元素的值,建立到头结点的单链表L
 28     int n;
 29     LinkList s;  // 定义一个指针变量
 30     L= new LNode;
 31     L->next= NULL;  // 先建立一个带头节点的空链表
 32     cout << "请输入元素个数n:" << endl;
 33     cin >> n;
 34     cout << "请以此输入n个元素:" << endl;
 35     cout << "前插法创建单链表..." << endl;
 36     while(n--){
 37         s = new LNode;  // 生成新结点
 38         cin >> s->data;  // 输入元素值给新节点的数据域
 39         s->next= L->next;
 40         L->next = s;  // 将新结点s插入到头结点之后
 41     }
 42 }
 43 
 44 void CreateList_R(LinkList &L){  // 尾插法创建单链表 正序
 45     // 输入n个元素的值,建立到带表头结点的单链表L
 46     int n;
 47     LinkList s, r;
 48     L = new LNode;
 49     L->next = NULL;  // 先建立一个带头结点的空链表
 50     r = L;  // 尾指针r指向头结点
 51     cout << "请输入元素个数n:" << endl;
 52     cin >> n;
 53     cout << "请以此输入n个元素:" << endl;
 54     cout << "尾插法创建单链表..." << endl;
 55     while (n--) {
 56         s = new LNode;  // 生成新结点
 57         cin >> s->data;  // 输入元素值赋值给新结点的数据域
 58         s->next = NULL;   // s就是最后一个
 59         r->next = s;  // 将新结点s插入尾结点*r之后
 60         r = s;  // r指向新的尾结点s
 61     }
 62 }
 63 
 64 bool GetElem_L(LinkList L, int i, int &e){  // 单链表的取值  e引用参数
 65     // 在带头结点的单链表L中查找第i个元素
 66     // 用e记录L中第i个元素的值
 67     int j;
 68     LinkList p;
 69     p = L->next;  // p指向第一个结点
 70     j = 1; // j为技术器
 71     while(j<i && p){  // 顺链域向后扫描,直到p指向第i个元素或者p为空
 72         p = p->next;  //p指向小一个结点
 73         j++;  // 计数器j相应加1
 74     }
 75     if(!p || j>i)
 76         return false;   // i值不合法i>n 或 i<=0
 77     e = p->data;
 78     return true;
 79     
 80 }
 81 
 82 bool LocateElem_L(LinkList L, int e){  // 按值查找
 83     //  在带头结点的单链表L中查找值为e的元素
 84     LinkList p;
 85     p = L->next;   // L指针不能动,会破坏链表
 86     while (p && p->data!=e)  // 顺链域向后扫描,直到p为空或p所指向结点的数据域等于e
 87     {
 88         p = p->next;   // p指向下一个结点
 89     }
 90     if(!p)
 91         return false;  // 查找失败p为NULL
 92     return true;
 93 }
 94 
 95 bool ListInsert_L(LinkList &L, int i, int e){  // 单链表的插入
 96     // 带头j结点的单链表L中第一个位置插入值为e的新结点
 97     int j;
 98     LinkList p, s;
 99     p = L;
100     j = 0;
101     while (p && j<i-1) {  // 查找第i-1个结点,p指向该结点
102         p = p->next;
103         j++;
104     }
105     if(!p || j>i-1)  // i>n+1 或者 i<1
106         return false;
107     s = new LNode;  // 生成新节点
108     s->data = e;  // 将新节点的数据域置为e
109     s->next = p->next;  // 将新结点的指针域指向节点ai
110     p->next = s;  // 将结点p的指针域指向结点s
111     return true;
112 }
113 
114 bool ListDelect_L(LinkList &L, int i){  // 单链表的删除
115     // 在带头结点的单链表L中,删除第i个位置
116     LinkList p, q;
117     int j;
118     p = L;
119     j = 0;
120     while ((p->next) && (j<i-1))
121     {
122         p = p->next;
123         j++;
124     }
125     if(!(p->next) || (j>i-1)){  // 当i>n 或i<1时,删除位置不合理
126         return false;
127     }
128     q = p->next;   // 临时保存被删除节点的地址以被释放空间
129     p->next = q->next; // 改变删除节点前驱结点的指针域
130     delete q;   // 释放被删除结点的空间
131     return true;
132 }
133 
134 void Listprint_L(LinkList L) //单链表的输出
135 {
136     LinkList p;
137     p = L->next;
138     while (p)
139     {
140         cout << p->data << "\t";
141         p = p->next;
142     }
143     cout << endl;
144     
145 }
146 
147 int main(){
148     int i, x, e, choose;
149     LinkList L;
150     cout << "1.初始化\n";
151     cout << "2.创建单链表(前插法)\n";
152     cout << "3.创建单链表(尾插法)\n";
153     cout << "4.取值\n";
154     cout << "5.查找\n";
155     cout << "6.插入\n";
156     cout << "7.删除\n";
157     cout << "8.输入\n";
158     cout << "0.退出\n";
159     choose = -1;
160     while (choose != 0)
161     {
162         cout << "请输入数字选择:";
163         cin >> choose;
164         switch (choose)
165         {
166         case 1:
167             if(InitList_L(L)){  // 初始化一个空的单链表
168                 cout << "初始化一个空的单链表!\n";
169             }
170             break;
171         case 2: // 创建单链表(前插法)
172             CreateList_H(L);
173             cout << "前插法创建单链表输出结果:\n"  << endl;
174             Listprint_L(L);
175             break; 
176         case 3: // 创建单链表(尾插法)
177             CreateList_R(L);
178             cout << "尾插法创建单链表输出结果:\n" << endl;
179             Listprint_L(L);
180             break;
181         case 4:  // 单链表的按序号取值
182             cout << "请输入一个位置用来取值:" << endl;
183             cin >> i;
184             if(GetElem_L(L, i, e)){
185                 cout << "查找成功\n";
186                 cout << "" << i << "个元素是:" << e << endl;
187             } else
188             {
189                 cout << "查找失败\n" << endl;
190             }
191             break;
192         case 5:  // 单链表的按值查找
193             cout << "请输入所要查找元素x" << endl;
194             cin >> x;
195             if(LocateElem_L(L,x))
196                 cout << "查找成功" << endl;
197             else
198                 cout << "查找失败!" << endl;
199             break;
200         case 6:  // 单链表插入
201             cout << "请输入出入的位置和元素(用空格隔开):";
202             cin >> i;
203             cin >> x;
204             if(ListInsert_L(L, i, x))
205                 cout << "插入成功" << endl;
206             else
207                 cout << "插入失败!" << endl;
208             break;
209         case 7:  // 单链表删除
210             cout << "请输入所有删除的元素位置i:"  << endl;
211             cin >> i;
212             if(ListDelect_L(L, i))
213                 cout << "当前单链表的数据元素分别为:" << endl;
214                 Listprint_L(L);
215                 cout << endl;
216                 break;
217         }
218     }
219     
220     return 0;
221 }
View Code

 

通过传递应用变量来获取返回值  e。

 1 case 4:  // 单链表的按序号取值
 2    cout << "请输入一个位置用来取值:" << endl;
 3    cin >> i;
 4    if(GetElem_L(L, i, e)){
 5        cout << "查找成功\n";
 6        cout << "" << i << "个元素是:" << e << endl;
 7     } else 9         cout << "查找失败\n" << endl;11    break;
 1 bool GetElem_L(LinkList L, int i, int &e){  // 单链表的取值
 2     // 在带头结点的单链表L中查找第i个元素
 3     // 用e记录L中第i个元素的值
 4     int j;
 5     LinkList p;
 6     p = L->next;  // p指向第一个结点
 7     j = 1; // j为技术器
 8     while(j<i && p){  // 顺链域向后扫描,直到p指向第i个元素或者p为空
 9         p = p->next;  //p指向小一个结点
10         j++;  // 计数器j相应加1
11     }
12     if(!p || j>i)
13         return false;   // i值不合法i>n 或 i<=0
14     e = p->data;
15     return true;
16     
17 }

2、两个非递减链表合并

Lc辅助头指正   重复利用头结点

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 typedef struct LNode
 7 {
 8     int data; 
 9     struct LNode *next;
10 }LNode, *LinkList;
11 
12 void CreateList_R(LinkList &L){
13     int n;
14     LinkList s, r;
15     L = new LNode;
16     L->next = NULL;
17     r = L;
18     cout << "请输入元素个数n:" << endl;
19     cin >> n;
20     cout << "请依次输入n个整型数(非递归):" << endl;
21     cout << "尾插法创建单链表..." << endl;
22     while (n--)
23     {
24         s = new LNode;
25         cin >> s->data;
26         s->next = NULL;
27         r->next = s;  // 将新节点s插入尾结点r之后
28         r = s; // r指向新的尾结点s
29     }
30 }
31 
32 void mergelinklist(LinkList La, LinkList Lb, LinkList &Lc){
33     LinkList p, q, r;  // 结构体指针变量
34     p = La->next;
35     q = Lb->next;
36     Lc = La;  // 这里Lc是没有创建的,而是直接借鉴La来创建链表
37     r = Lc;  // r指向Lc的尾部
38     while(p && q){
39         if(p->data <= q->data){  // 把p指向的结点串起来
40             r->next = p;
41             r = p;
42             p = p->next;  // p更新  p后移一个结点
43         }else{
44             r->next = q;
45             r = q;
46             q = q->next;  // q更新  q后移一个结点
47         }
48     }
49     r->next = p ? p : q;
50     delete Lb;
51 }
52 
53 void Listprint_L(LinkList L){
54     LinkList p;
55     p = L->next;
56     while (p)
57     {
58         cout << p->data << "\t";
59         p = p->next;
60     }
61     cout <<  endl;
62     
63 }
64 
65 
66 int main(){
67     LinkList La, Lb, Lc;
68     cout << "创建有序(非递减)单链表La" << endl;
69     CreateList_R(La);
70     cout << "创建有序(非递减)单链表Lb" << endl;
71     CreateList_R(Lb);
72     mergelinklist(La, Lb, Lc);
73     cout << "合并后的结果Lc:" << endl;
74     Listprint_L(Lc);
75     return 0;
76 }
View Code

3、单链表 高效 取中间节点   

思路:快慢指针

链表长度为7 中间节点为4

链表长度为6 中间节点为3

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 typedef struct LNode{
 6     int data;
 7     struct LNode *next;
 8 }LNode, *LinkList;
 9 
10 void CreateList_R(LinkList &L){
11     int n;
12     LinkList s, r;
13     L = new LNode;
14     L->next = NULL;
15     r = L;
16     cout << "请输入元素个数n:" << endl;
17     cin >> n;
18     cout << "尾插法(正序)创建单链表..." << endl;
19     while (n--)
20     {
21         s = new LNode;
22         cin >> s->data;
23         s->next = NULL;
24         r->next = s;
25         r =s;
26     }
27 }
28 
29 LinkList findmiddle(LinkList L){ // 快慢指针找中间元素
30     LinkList fast, slow;
31     fast = L;
32     slow = L;
33     while (fast!=NULL && fast->next!=NULL)
34     {
35         fast = fast->next->next;
36         slow = slow->next;
37     }
38     return slow;
39 }
40 
41 void Listprint_L(LinkList L){
42     LinkList p;
43     p = p->next;
44     while (p)
45     {
46         cout << p->data << "\t";
47         p = p->next;
48     }
49     cout << endl;
50 }
51  
52 int main(){
53     LinkList L, mid;
54     cout << "创建单链表L:" << endl;
55     CreateList_R(L);
56     mid = findmiddle(L);
57     cout << "单链表中间节点数据为:" << mid->data << endl;
58     return 0;
59 }
View Code

猜你喜欢

转载自www.cnblogs.com/JCcodeblgos/p/11408173.html