数据结构02:链表

[复制链接]
1048|0
 楼主| seifguo 发表于 2016-3-26 23:10 | 显示全部楼层 |阅读模式
  1. /*
  2. * 根据郝斌老师视频整理
  3. * 编译环境:
  4. * guo@linux:~$ gcc --version
  5. * gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
  6. */
  7. #include <stdio.h>
  8. #include <malloc.h>
  9. #include <stdlib.h>

  10. #define FALSE 0
  11. #define TRUE  1

  12. typedef struct Node
  13. {
  14.         int data;                         /*数据域*/
  15.         struct Node *pNext; /*指针域*/
  16. }NODE, *PNODE;

  17. /**********************声明**********************************/
  18. /*创建链表*/
  19. PNODE CreateLink(void);
  20. /*遍历链表*/
  21. void  TraverseLink(PNODE );
  22. /*判断链表是否为空*/
  23. int   IsEmptyLink(PNODE );
  24. /*求链表长度*/
  25. int   LengthLink(PNODE );
  26. /*链表排序*/
  27. void  SortLink(PNODE );
  28. /*链表插入节点*/
  29. int   InsertLink(PNODE , int , int );
  30. /*链表删除节点*/
  31. int   DeleteLink(PNODE , int , int *);

  32. /*
  33. * 函数名称:CreateLink。
  34. * 输入参数:无。
  35. * 输出参数:返回头节点的指针。
  36. * 函数说明:创建一个链表,并由用户输入每个节点的值。
  37. */
  38. PNODE CreateLink(void)
  39. {
  40.         int len;                /*链表个数*/
  41.         int val;                /*存储临时值*/
  42.         int i;

  43.         /*为头节点分配内存,并把地址赋值给pHead*/
  44.         PNODE pHead = (PNODE)malloc(sizeof(NODE));
  45.         if (NULL == pHead)
  46.         {
  47.                 printf("内存分配失败!\n");
  48.                 exit(-1);
  49.         }
  50.         PNODE pTail = pHead;
  51.         pTail->pNext = NULL;

  52.         printf("请输入链表的个数:len=\n");
  53.         scanf("%d",&len);

  54.         for (i=0;i<len;++i)
  55.         {
  56.                 PNODE pNew = (PNODE)malloc(sizeof(NODE));
  57.                 if (NULL == pNew)
  58.                 {
  59.                         printf("内存分配失败!\n");
  60.                         exit(-1);
  61.                 }
  62.                 printf("请输入第%d个节点的值:\n",i+1);
  63.                 scanf("%d",&val);

  64.                
  65.                 pNew->data = val;           /*保存新节点的数据*/
  66.                 pNew->pNext = NULL;                /*新节点的指针指向NULL*/
  67.                 pTail->pNext = pNew;        /*上个节点的指针指向新节点*/
  68.                 pTail = pNew;                        /*pTail指向新节点(保存新节点地址)*/
  69.         }
  70.    
  71.         return pHead;
  72. }

  73. /*
  74. * 函数名称:TraverseLink。
  75. * 输入参数:pHead链表头节点的指针。
  76. * 输出参数:无。
  77. * 函数说明:遍历一个链表,并输出每个节点的值。
  78. */
  79. void TraverseLink(PNODE pHead)
  80. {
  81.         PNODE p = pHead->pNext; //p指向第一个有效节点(首节点)
  82.         while(NULL != p)
  83.         {
  84.                 printf("%d ", p->data);
  85.                 p = p->pNext;
  86.         }
  87.         printf("\n");

  88.         return;
  89. }

  90. /*
  91. * 函数名称:IsEmptyLink。
  92. * 输入参数:pHead链表头节点的指针。
  93. * 输出参数:为空返回TRUE;否则返回FALSE。
  94. * 函数说明:判断一个链表是否为空。
  95. */
  96. int IsEmptyLink(PNODE pHead)
  97. {
  98.         if (NULL == pHead->pNext)
  99.                 return TRUE;
  100.         else
  101.                 return FALSE;
  102. }

  103. /*
  104. * 函数名称:LengthLink。
  105. * 输入参数:pHead链表头节点的指针。
  106. * 输出参数:链表长度。
  107. * 函数说明:求链表长度。
  108. */
  109. int LengthLink(PNODE pHead)
  110. {
  111.         int len = 0;
  112.         PNODE p = pHead->pNext;
  113.        
  114.         while (NULL != p)
  115.         {
  116.                 ++len;
  117.                 p = p->pNext;
  118.         }

  119.         return len;
  120. }

  121. /*
  122. * 函数名称:SortLink。
  123. * 输入参数:pHead链表头节点的指针。
  124. * 输出参数:无。
  125. * 函数说明:选择排序,升序。
  126. */
  127. void SortLink(PNODE pHead)
  128. {
  129.         int i,j,t,len;
  130.         PNODE p,q;

  131.         len = LengthLink(pHead);

  132.         /*i,j决定循环次数*/
  133.         for (i=0,p=pHead->pNext;i<len-1;++i,p=p->pNext)
  134.         {
  135.                 for(j=i+1,q=p->pNext;j<len;++j,q=q->pNext)
  136.                 {
  137.                         if (p->data > q->data)
  138.                         {
  139.                                 t = p->data;
  140.                                 p->data = q->data;
  141.                                 q->data = t;
  142.                         }
  143.                 }
  144.         }
  145.         return;
  146. }

  147. /*
  148. * 函数名称:InsertLink。
  149. * 输入参数:pHead链表头节点的指针;pos要插入的位置,从1开始;value要插入的值;
  150. *           pos可以比链表长度大1。
  151. * 输出参数:插入成功返回TRUE,否则返回FALSE。
  152. * 函数说明:插入一个节点。
  153. *   假设有5个节点,如下所示:
  154. *   pHead 节点1  节点2  节点3  节点4  节点5
  155. *   OOOO——>OOOO——>OOOO——>OOOO——>OOOO——>OOOO
  156. *   假设pos=3,即在第三个节点前插入数值。在while语句中带入数值:
  157. *   1)初始值: i=0,p指向pHead
  158. *   2)while成立:i=1,p指向节点1
  159. *   3)while成立:i=2,p指向节点2
  160. *   4)2<3-1不成立,所以此时可以确定pos没有超过链表长度,p正好指向第三个节点的
  161. *     前一个节点。
  162. *   5)如果只有2个节点,pos=3的话,在经过3)后,p指向节点2,此时p!= NULL,
  163. *     p->pNext = NULL。此时while语句的前半部分成立,后半部分不成立,所以while的
  164. *     判断条件适合pos的值可以比链表的长度大1.
  165. */
  166. int InsertLink(PNODE pHead, int pos, int value)
  167. {
  168.         int i = 0;
  169.         PNODE p = pHead;

  170.         /*利用循环找到pos位置,或者到尾节点*/
  171.         while (NULL!=p && i<pos-1)
  172.         {
  173.                 p = p->pNext;
  174.                 ++i;
  175.         }
  176.         /*从while循环中可以得知,i>pos-1不会成立,在此加一个是为了保证逻辑严密??*/
  177.         /*如果因为NULL==p导致while退出循环,说明pos超过链表的长度*/
  178.         if (i>pos-1 || NULL==p)
  179.                 return FALSE;

  180.         PNODE pNew = (PNODE)malloc(sizeof(NODE));
  181.         if (NULL == pNew)
  182.         {
  183.                 printf("动态分配内存失败!\n");
  184.                 exit(-1);
  185.         }
  186.         pNew->data = value;
  187.         pNew->pNext = p->pNext;
  188.         p->pNext = pNew;

  189.         return TRUE;
  190. }

  191. /*
  192. * 函数名称:DeleteLink。
  193. * 输入参数:pHead链表头节点的指针;pos要删除的位置,从1开始;value保存要删除节点的值。
  194. * 输出参数:删除成功返回TRUE,否则返回FALSE。
  195. * 函数说明:删除一个节点。思路跟InsertLink相同,注意要释放内存。
  196. */
  197. int DeleteLink(PNODE pHead, int pos, int *pValue)
  198. {
  199.         int i = 0;
  200.         PNODE p = pHead;

  201.         while (NULL!=p && i<pos-1)
  202.         {
  203.                 p = p->pNext;
  204.                 ++i;
  205.         }
  206.         if (i>pos-1 || NULL == p)
  207.                 return FALSE;
  208.         /*此时p指向pos的前一个节点*/
  209.         *pValue = p->pNext->data;
  210.         PNODE q = p->pNext;
  211.         p->pNext = p->pNext->pNext;
  212.         free(q);
  213.         q = NULL;

  214.         return TRUE;
  215. }

  216. int main(void)
  217. {
  218.         PNODE pHead = NULL;
  219.         int DeleteVal; /*存储删除的值*/

  220.         pHead = CreateLink();
  221.         TraverseLink(pHead);

  222.         if (IsEmptyLink(pHead))
  223.                 printf("链表为空!\n");
  224.         else
  225.                 printf("链表非空!\n");

  226.         printf("链表长度为%d\n",LengthLink(pHead));

  227.         printf("链表按升序排列为:\n");
  228.         SortLink(pHead);
  229.         TraverseLink(pHead);

  230.         printf("链表插入一个值:\n");
  231.         InsertLink(pHead, 3, 33);
  232.         TraverseLink(pHead);

  233.         printf("链表删除一个值:\n");
  234.         DeleteLink(pHead, 2, &DeleteVal);
  235.         TraverseLink(pHead);
  236.         printf("链表删除的值为%d:\n",DeleteVal);
  237.         return 0;
  238. }


您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

83

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部