当前位置:   article > 正文

C语言:带头结点的单链表的表示与实现(包含常见的14种基本操作)_c语言[问题描述] 实现带头结点的单链表的建立、求长度,取元素、修改元素、插入、

c语言[问题描述] 实现带头结点的单链表的建立、求长度,取元素、修改元素、插入、

完整代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. //函数结果状态代码
  4. #define TRUE 1
  5. #define FALSE 0
  6. #define OK 1
  7. #define ERROR 0
  8. #define INFEASIBLE -1
  9. #define OVERFLOW -2
  10. //给int定义别名为status,当函数返回值是为状态码时,可用status作为函数类型,更方便理解
  11. typedef int Status;
  12. //定义单链表的结构体
  13. typedef struct LNode
  14. {
  15. int data;//单链表所存储的值
  16. struct LNode *next;//指针指向下一个结点
  17. }LNode,*LinkList;//LNode *强调是一共结点,LinkList强调是一个单链表
  18. //初始化一个空的,带头结点的单链表
  19. Status InitList(LinkList *L);
  20. //判断单链表是否为空
  21. Status IsEmptyList(LinkList L);
  22. //销毁单链表
  23. Status DestroyList(LinkList *L);
  24. //清空单链表
  25. Status ClearList(LinkList L);
  26. //求单链表表长,返回值为表长
  27. int LengthList(LinkList L);
  28. //头插法建立单链表,创建n个元素
  29. Status CreateHeadList(LinkList *L,int n);
  30. //尾插法建立单链表,创建n个元素
  31. Status CreateTailList(LinkList *L,int n);
  32. //获取第i个数据元素,并存入e中
  33. Status GetElemList(LinkList L,int i,int *e);
  34. //在单链表第i个位置前插入元素e
  35. Status InsertList(LinkList L,int i,int e);
  36. //按值查找数据所在地址并返回所查询数据的地址
  37. LinkList SearchList(LinkList L,int e);
  38. //按值查找数据所在位序并返回
  39. int LocateList(LinkList L,int e);
  40. //删除在链表中位序为i的结点
  41. Status DeleteList(LinkList L,int i);
  42. //遍历打印单链表数据6
  43. void PrintList(LinkList L);
  44. //合并两个有序链表A,B为一个有序链表C
  45. Status MergeList(LinkList A,LinkList B,LinkList *C);
  46. int main(){
  47. LinkList L;
  48. LinkList L1;
  49. printf("%d\n",InitList(&L));
  50. printf("%d\n",IsEmptyList(L));
  51. // CreateHeadList(&L1,4);//头插法
  52. CreateTailList(&L1,6);//尾插法
  53. printf("表长为%d\n",LengthList(L1));
  54. PrintList(L1);
  55. int e;
  56. GetElemList(L1,2,&e);
  57. printf("你所查找的元素为%d\n",e);
  58. InsertList(L1,1,6);//添加一个结点
  59. printf("你查找元素的地址为%p\n",SearchList(L1,3));
  60. printf("你查找元素的位序为%d\n",LocateList(L1,3));
  61. DeleteList(L1,6);//删除一个结点
  62. PrintList(L1);
  63. printf("%d\n",IsEmptyList(L1));
  64. ClearList(L1);
  65. PrintList(L1);
  66. DestroyList(&L1);
  67. printf("-----------\n");
  68. printf("-----------\n");
  69. printf("-----------\n");
  70. //测试合并函数功能
  71. LinkList A,B,C;
  72. InitList(&C);
  73. CreateTailList(&A,4);
  74. CreateTailList(&B,4);
  75. MergeList(A,B,&C);
  76. printf("合并后的链表C为");
  77. PrintList(C);
  78. return 0;
  79. }
  80. //初始化一个空的,带头结点的单链表
  81. Status InitList(LinkList *L){
  82. *L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
  83. if (*L==NULL)
  84. {
  85. printf("分配内存失败\n");
  86. exit(OVERFLOW);
  87. }
  88. (*L)->next=NULL;//将头节点的后继置空
  89. return OK;
  90. }
  91. //判断单链表是否为空
  92. Status IsEmptyList(LinkList L){
  93. //只需判断头节点是否有后继
  94. if (L->next==NULL)
  95. {
  96. printf("当前单链表为空\n");
  97. return TRUE;
  98. }
  99. else
  100. {
  101. printf("当前单链表不为空\n");
  102. return FALSE;
  103. }
  104. }
  105. //销毁单链表
  106. Status DestroyList(LinkList *L){
  107. LinkList p=*L;
  108. //free所有的结点包括头结点
  109. while (*L)
  110. {
  111. *L=(*L)->next;
  112. free(p);
  113. p=*L;
  114. }
  115. printf("链表已销毁\n");
  116. return OK;
  117. }
  118. //清空单链表
  119. Status ClearList(LinkList L){
  120. //free所有结点,不包括头结点
  121. LinkList p,q;
  122. p=L->next;
  123. //p为NULL时说明链表已经全部清空
  124. while (p)
  125. {
  126. q=p->next;
  127. free(p);
  128. p=q;
  129. }
  130. //头结点指向NULL,此时链表为空表
  131. L->next=NULL;
  132. printf("链表已清空\n");
  133. return OK;
  134. }
  135. //求单链表表长,返回值为表长
  136. int LengthList(LinkList L){
  137. LinkList p;
  138. int count=0;//记录表长
  139. p=L->next;
  140. while (p)
  141. {
  142. count++;
  143. p=p->next;
  144. }
  145. return count;
  146. }
  147. //头插法建立单链表,创建n个元素
  148. Status CreateHeadList(LinkList *L,int n){
  149. LinkList p,r;//p指向新结点,r指向头节点
  150. *L=(LinkList)malloc(sizeof(LNode));//创建头结点
  151. if (*L==NULL)
  152. {
  153. printf("分配内存失败\n");
  154. exit(OVERFLOW);
  155. }
  156. r=*L;
  157. r->next=NULL;//避免脏数据
  158. for (int i = n; i >0; i--)
  159. {
  160. p=(LNode *)malloc(sizeof(LNode));//生成新的结点
  161. printf("请输入链表的第%d个元素\n",i);
  162. scanf("%d",&p->data);
  163. //插入到表头
  164. p->next=NULL;//避免脏数据
  165. p->next=r->next;
  166. r->next=p;
  167. }
  168. printf("创建完毕\n");
  169. return OK;
  170. }
  171. //尾插法建立单链表,创建n个元素
  172. Status CreateTailList(LinkList *L,int n){
  173. LinkList p,r;//p指向新结点,r指向链表尾部结点
  174. *L=(LinkList)malloc(sizeof(LNode));//创建头结点
  175. if (*L==NULL)
  176. {
  177. printf("分配内存失败\n");
  178. exit(OVERFLOW);
  179. }
  180. r=*L;
  181. r->next=NULL;
  182. for (int i = 0; i <n; i++)
  183. {
  184. p=(LinkList)malloc(sizeof(LNode));//生成新的结点
  185. if (!p)
  186. {
  187. printf("分配内存失败\n");
  188. exit(OVERFLOW);
  189. }
  190. printf("请输入链表的第%d个元素\n",i+1);
  191. scanf("%d",&p->data);
  192. //插入到表头
  193. p->next=NULL;//避免脏数据
  194. r->next=p;
  195. r=r->next;//将尾部指针移向新的结点p,然后p就变成新的尾部结点
  196. }
  197. r->next=NULL;
  198. printf("创建完毕\n");
  199. return OK;
  200. }
  201. //获取第i个数据元素,并存入e中
  202. Status GetElemList(LinkList L,int i,int *e){
  203. LNode *p;
  204. p=L->next;
  205. int j=1;
  206. //通过循环到达第i个元素
  207. while (p&&j<i)
  208. {
  209. p=p->next;
  210. j++;
  211. }
  212. //当i不合法时不能查询
  213. if (!p||j>i){
  214. printf("查询不到该元素\n");
  215. return ERROR;
  216. }
  217. *e=p->data;
  218. return OK;
  219. }
  220. //在单链表第i个位置前插入元素e
  221. Status InsertList(LinkList L,int i,int e){
  222. LinkList p,s;
  223. p=L;//指向头结点
  224. s=(LNode *)malloc(sizeof(LNode));//建立要插入的结点
  225. if (!s)
  226. {
  227. printf("分配内存失败\n");
  228. exit(OVERFLOW);
  229. }
  230. s->data=e;
  231. s->next=NULL;
  232. int j=0;
  233. //通过循环到达第i-1个元素
  234. while (p&&j<i-1)
  235. {
  236. p=p->next;
  237. j++;
  238. }
  239. if(!p||j>i-1) return ERROR;//当i不合法时不能插入
  240. s->next=p->next;
  241. p->next=s;
  242. printf("插入元素成功\n");
  243. return OK;
  244. }
  245. //按值查找数据所在地址并返回所查询数据的地址
  246. LinkList SearchList(LinkList L,int e){
  247. LNode *p;
  248. p=L->next;
  249. while (p)
  250. {
  251. if (p->data==e) return p;
  252. p=p->next;
  253. }
  254. printf("没有找到该数据\n");
  255. return NULL;
  256. }
  257. //按值查找数据所在位序并返回
  258. int LocateList(LinkList L,int e){
  259. LNode *p;
  260. int j=1;
  261. p=L->next;
  262. while (p)
  263. {
  264. if (p->data==e) return j;
  265. p=p->next;
  266. j++;
  267. }
  268. printf("没有找到该数据\n");
  269. return ERROR;
  270. }
  271. //删除在链表中位序为i的结点
  272. Status DeleteList(LinkList L,int i){
  273. LinkList p,q;
  274. p=L;
  275. //让p到达位序为i-1
  276. for (int j = 0; p&&j < i-1; j++)
  277. {
  278. p=p->next;
  279. }
  280. q=p->next;//q为被删除的结点
  281. if (!q)
  282. {
  283. printf("i的值不合法\n");
  284. return ERROR;
  285. }
  286. p->next=q->next;
  287. free(q);
  288. printf("删除成功\n");
  289. return OK;
  290. }
  291. //遍历打印单链表数据
  292. void PrintList(LinkList L){
  293. LinkList p=L->next;
  294. if (!p)
  295. {
  296. printf("链表为空,无法打印\n");
  297. }else{
  298. printf("单链表为Head");
  299. }
  300. while (p)
  301. {
  302. printf("->%d",p->data);
  303. p=p->next;
  304. }
  305. printf("\n");
  306. }
  307. //合并两个有序链表A,B为一个有序链表C
  308. Status MergeList(LinkList A, LinkList B, LinkList *C) {
  309. LNode *pa;
  310. LNode *pb;
  311. LNode *pc;
  312. pa = A->next;
  313. pb = B->next;
  314. pc =*C;//pc为遍历和操作链表 C 的指针
  315. while (pa && pb) {
  316. if (pa->data <= pb->data) {
  317. pc->next = pa;
  318. pc = pc->next;
  319. pa = pa->next;
  320. } else {
  321. pc->next = pb;
  322. pc = pc->next;
  323. pb = pb->next;
  324. }
  325. }
  326. //插入剩余段
  327. if (pa != NULL) pc->next = pa;
  328. if (pb != NULL) pc->next = pb;
  329. free(B);
  330. printf("合并成功\n");
  331. return OK;
  332. }

运行截图:

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号