一.单向链表:
由于线性表的顺序存储结构(数组),在插入和删除需要移动大量元素以及其他特殊情况下,效率低下,耗时费力,此处引入了链表的概念。
链表的基本组成单元为结点(node),包括两个域:存储数据元素信息的域->数据域;存储直接后继存储位置的域(指针)->指针域。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <time.h> 4 #define OK 1 5 #define ERROR 0 6 7 8 typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 9 typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */ 10 11 typedef struct Node 12 { 13 ElemType data; 14 struct Node *next; 15 }Node; 16 typedef struct Node *LinkList; //定义LinkList 17 18 Status InitList(LinkList *L); 19 Status Destroy(LinkList L); 20 Status ClearList(LinkList *L); 21 bool ListEmpty(LinkList L); 22 int ListLength(LinkList L); 23 Status GetElem(LinkList L,int i,ElemType *e); 24 int LocateElem(LinkList L,ElemType e); 25 Status PriorElem(LinkList *L, ElemType cur_e, LinkList *pre_e); 26 Status NextElem(LinkList *L, ElemType cur_e, LinkList *next_e); 27 Status ListInsert(LinkList *L,int i,ElemType e); 28 Status ListDelete(LinkList *L,int i,ElemType *e); 29 Status ListTraverse(LinkList L); 30 void CreateListHead(LinkList *L, int n); 31 void CreateListTail(LinkList *L, int n); 32 33 Status visit(ElemType c) 34 { 35 printf("%d ",c); 36 return OK; 37 } 38 39 /*初始化顺序线性表: 构造一个空的线性表L*/ 40 Status InitList(LinkList *L) 41 { 42 *L = (LinkList)malloc(sizeof(Node)); /* 产生头结点,并使L指向此头结点,L为头指针 */ 43 if(!(*L)) /* 存储分配失败 */ 44 return ERROR; 45 (*L)->next = NULL; /* 指针域为空 */ 46 47 return OK; 48 } 49 /*初始条件:线性表L已存在。操作结果:销毁线性表L*/ 50 Status Destroy(LinkList L) 51 { 52 ClearList(&L); 53 free(L); 54 L = NULL; 55 } 56 57 /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */ 58 Status ClearList(LinkList *L) 59 { 60 LinkList p,q; 61 p=(*L)->next; /* p指向第一个结点 */ 62 while(p) /* 没到表尾 */ 63 { 64 q=p->next; 65 free(p); 66 p=q; 67 } 68 (*L)->next = NULL; /* 头结点指针域为空 */ 69 return OK; 70 } 71 72 /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */ 73 bool ListEmpty(LinkList L) 74 { 75 if(L->next) 76 return false; 77 else 78 return true; 79 } 80 81 /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */ 82 int ListLength(LinkList L) 83 { 84 int i = 0; 85 LinkList p=L->next; /* p指向第一个结点 */ 86 while(p) 87 { 88 i++; 89 p=p->next; 90 } 91 return i; 92 } 93 94 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) 95 操作结果:用e返回L中第i个数据元素的值 */ 96 Status GetElem(LinkList L,int i,ElemType *e) 97 { 98 int j = 1; /* j为计数器 */ 99 LinkList p; /* 声明一结点p */ 100 p = L->next; /* 让p指向链表L的第一个结点 */ 101 while (p && j < i) { /* p不为空或者计数器j还没有等于i时,循环继续 */ 102 p = p->next; /* 让p指向下一个结点 */ 103 j++; 104 } 105 if ( !p || j>i ) 106 return ERROR; /* 第i个元素不存在 */ 107 *e = p->data; /*取第i个元素的数据 */ 108 return OK; 109 } 110 111 /* 初始条件:顺序线性表L已存在 112 操作结果:返回L中第1个与e满足关系的数据元素的位序。 113 若这样的数据元素不存在,则返回值为0 */ 114 int LocateElem(LinkList L,ElemType e) 115 { 116 int i=0; 117 LinkList p=L->next; 118 while(p) 119 { 120 i++; 121 if(p->data==e) /* 找到这样的数据元素 */ 122 return i; 123 p=p->next; 124 } 125 126 return 0; 127 } 128 129 /*初始条件:线性表L已存在 130 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, 131 否则操作失败,pre_e无定义*/ 132 Status PriorElem(LinkList *L, ElemType cur_e, LinkList *pre_e) 133 { 134 LinkList p; 135 p = (*L)->next; 136 if(p->data == cur_e) { /* 是第一个 */ 137 pre_e = NULL; 138 return ERROR; 139 } 140 while(p->next) 141 { 142 if(p->next->data == cur_e) { 143 *pre_e = p; 144 return OK; 145 } 146 p = p->next; 147 } 148 pre_e = NULL; 149 return ERROR; 150 } 151 152 /*初始条件:线性表L已存在 153 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后驱, 154 否则操作失败,next_e无定义*/ 155 Status NextElem(LinkList *L, ElemType cur_e, LinkList *next_e) 156 { 157 LinkList p; 158 p = (*L); 159 while(p->next) 160 { 161 if(p->data == cur_e) { 162 *next_e = p->next; 163 return OK; 164 } 165 p = p->next; 166 } 167 *next_e = NULL; 168 return ERROR; 169 } 170 171 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) + 1, 172 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */ 173 Status ListInsert(LinkList *L,int i,ElemType e) 174 { 175 int j = 1; 176 LinkList p,s; 177 p = *L; 178 while (p && j < i) { /* 寻找第i个结点 */ 179 p = p->next; 180 ++j; 181 } 182 if (!p || j > i) 183 return ERROR; /* 第i个元素不存在 */ 184 s = (LinkList)malloc(sizeof(Node)); /* 生成新结点(C语言标准函数) */ 185 s->data = e; 186 s->next = p->next; /* 将p的后继结点赋值给s的后继 */ 187 p->next = s; /* 将s赋值给p的后继 */ 188 return OK; 189 } 190 191 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) 192 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */ 193 Status ListDelete(LinkList *L,int i,ElemType *e) 194 { 195 int j; 196 LinkList p,q; 197 p = *L; 198 j = 1; 199 while (p->next && j < i) { /* 遍历寻找第i个元素 */ 200 p = p->next; 201 ++j; 202 } 203 if (!(p->next) || j > i) 204 return ERROR; /* 第i个元素不存在 */ 205 q = p->next; 206 p->next = q->next; /* 将q的后继赋值给p的后继 */ 207 *e = q->data; /* 将q结点中的数据给e */ 208 free(q); /* 让系统回收此结点,释放内存 */ 209 return OK; 210 } 211 212 /* 初始条件:顺序线性表L已存在 213 操作结果:依次对L的每个数据元素输出 */ 214 Status ListTraverse(LinkList L) 215 { 216 LinkList p=L->next; 217 while(p) 218 { 219 visit(p->data); 220 p=p->next; 221 } 222 printf("\n"); 223 return OK; 224 } 225 226 /* 随机产生n个元素的值,建立带表头结点的单链线性表L(头插法) */ 227 void CreateListHead(LinkList *L, int n) 228 { 229 LinkList p; 230 int i; 231 srand(time(0)); /* 初始化随机数种子 */ 232 *L = (LinkList)malloc(sizeof(Node)); 233 (*L)->next = NULL; /* 先建立一个带头结点的单链表 */ 234 for (i=0; i<n; i++) 235 { 236 p = (LinkList)malloc(sizeof(Node)); /* 生成新结点 */ 237 p->data = rand()%100+1; /* 随机生成100以内的数字 */ 238 p->next = (*L)->next; 239 (*L)->next = p; /* 插入到表头 */ 240 } 241 } 242 243 /*建立带表头结点的单链线性表L(尾插法) */ 244 void CreateListTail(LinkList *L, int n) 245 { 246 LinkList p,r; 247 *L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */ 248 r = *L; /* r为指向尾部的结点 */ 249 for (int i = 0; i < n; i++) { 250 p = (Node *)malloc(sizeof(Node)); /* 生成新结点 */ 251 scanf("%d",p->data); 252 r->next = p; /* 将表尾终端结点的指针指向新结点 */ 253 r = p; /* 将当前的新结点定义为表尾终端结点 */ 254 } 255 r->next = NULL; /* 表示当前链表结束 */ 256 } 257 int main() 258 { 259 LinkList L, pre_e,next_e; //创建一个可以指向结点的指针 260 CreateListTail(&L,10); 261 ListInsert(&L,11,55); 262 ListTraverse(L); 263 PriorElem(&L, 3, &pre_e); 264 NextElem(&L, 3, &next_e); 265 printf("前驱%d\n",(*pre_e).data); 266 printf("后继%d\n",(*next_e).data); 267 Destroy(L); 268 269 270 return 0; 271 }