单向链表基本操作的递归实现

508阅读 0评论2012-08-15 jueduiyingxiong
分类:

这几天正在复习一些基本的算法和实现,今天看了看递归的基本原理,发现自己对递归还不是特别清楚,特别是不清楚递归的思想,不能很准确的把握先分解成小事件,在合并的思想,其实也是数学归纳法的程序体现,其实数学归纳法是一种强大的方法,记得高中的时候最喜欢做的题目就是数学归纳方面的证明,现在想过来好多问题我不能采用这种方式思考,可见知识真的是有联系的,只是我们没有找到联系的方式而已。
 
为了熟悉递归的思想,我尝试了采用递归的方式实现单向链表的基本操作。单向的链表是C语言课程中接触到的中比较复杂的数据结构,但是他确实其他数据结构的基础,在一般情况下都是采用迭代的形式实现,迭代的形式相比递归要节省时间和空间,但是代码相对来说要复杂,递归往往只是简单的几句代码,我主要是为了熟悉迭代,并不在性能上进行分析。
 
基本的实现如下所示:

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<stdlib.h>

  3. typedef struct listnode
  4. {
  5.         int val;
  6.         struct listnode *next;
  7. }List;

  8. /*统计节点个数*/
  9. int count_listnode(List *head)
  10. {
  11.         static int count = 0;
  12.     
  13.         if(NULL != head)
  14.         {
  15.                 count += 1;
  16.                 if(head->next != NULL)
  17.                 {
  18.                         count_listnode(head->next);
  19.                 }

  20.                 return count;
  21.         }
  22. }

  23. /*顺序打印*/
  24. void fdprint_listnode(List *head)
  25. {
  26.         if(NULL != head)
  27.         {
  28.                 printf("%d\t",head->val);
  29.                 if(head->next != NULL)
  30.                 {
  31.                         fdprint_listnode(head->next);
  32.                 }
  33.         }
  34. }
  35. /*反向打印*/
  36. void bkprint_listnode(List *head)
  37. {
  38.         if(head != NULL)
  39.         {
  40.                 if(head->next != NULL)
  41.                 {
  42.                         bkprint_listnode(head->next);
  43.                 }

  44.                 printf("%d\t",head->val);
  45.         }
  46. }
  47. /*删除一个节点的数据为d的节点*/
  48. List *delete_node(List * head, int d)
  49. {
  50.         List *temp = head;

  51.         if(head != NULL)
  52.         {
  53.                 if(head->val == d)
  54.                 {
  55.                         temp = head;
  56.                         head = head->next;
  57.                         free(temp);
  58.                         temp = NULL;
  59.                 }
  60.                 else
  61.                 {
  62.                         temp = head->next;
  63.                         if(temp != NULL)
  64.                         {
  65.                                 temp = delete_node(temp,d);
  66.                                 head->next = temp;
  67.                         }
  68.                 }
  69.         }

  70.         return head;
  71. }

  72. /*删除所有val = d的节点*/
  73. List* delete_allnode(List *head, int d)
  74. {
  75.         List *temp = head, *cur = head;
  76.         if(head != NULL)
  77.         {
  78.                 /*如果第一个就是需要删除的对象*/
  79.                 if(cur->val == d)
  80.                 {
  81.                         temp = cur;
  82.                         cur = cur->next;
  83.                         free(temp);
  84.                         temp = NULL;
  85.                         temp = delete_allnode(cur, d);
  86.                         head = temp;
  87.                 }
  88.                 else /*不是删除的对象*/
  89.                 {
  90.                         cur = head->next;
  91.                         temp = delete_allnode(cur, d);
  92.                         /*将得到的链表连接到检测的区域*/
  93.                         head->next = temp;
  94.                 }
  95.         }
  96.         return head;
  97. }
  98. /*最大值*/
  99. int max_list(List *head)
  100. {
  101.         int max = 0;
  102.         int temp;
  103.         if(NULL == head)
  104.         {
  105.                 printf("Error: NULL pointer...");
  106.         }

  107.         if(NULL != head && head->next == NULL)
  108.         {
  109.                 return head->val;
  110.         }

  111.         else
  112.         {
  113.                 temp = max_list(head->next);

  114.                 max = (head->val > temp ? head->val : temp);

  115.                 return max;
  116.         }
  117. }

  118. /*最小值*/
  119. int min_list(List *head)
  120. {
  121.         int min = 0;
  122.         int temp;

  123.         if(NULL == head)
  124.         {
  125.                 printf("Error: NULL pointer...");
  126.         }

  127.         if(NULL != head && head->next == NULL)
  128.         {
  129.                 return head->val;
  130.         }

  131.         else
  132.         {
  133.                temp = min_list(head->next);

  134.                 min = (head->val < temp ? head->val : temp);

  135.                 return min;
  136.         }
  137. }

  138. /*创建链表*/
  139. List* create_list(int val)
  140. {
  141.         List *head = (List *)malloc(sizeof(List)/sizeof(char));

  142.         if(NULL == head)
  143.         {
  144.                 return NULL;
  145.         }

  146.         head->val = val;

  147.         head->next = NULL;

  148.         return head;
  149. }

  150. /*插入节点*/
  151. List* insert_listnode(List *head, int val)
  152. {
  153.         List *temp;
  154.         if(NULL == head)
  155.         {
  156.                 return NULL;
  157.         }

  158.         temp = (List *)malloc(sizeof(List)/sizeof(char));
  159.         temp->val = val;
  160.         temp->next = head;
  161.         head = temp;

  162.         return head;
  163. }

  164. /*删除链表*/
  165. void delete_list(List *head)
  166. {
  167.         List *temp = NULL;
  168.         if(head != NULL)
  169.         {
  170.                 temp = head;
  171.                 head = head->next;
  172.                 free(temp);
  173.                 temp = NULL;

  174.                 delete_list(head);
  175.         }
  176. }

  177. int main()
  178. {
  179.         int n = 0;
  180.         int i = 0;
  181.         List * head = create_list(10);

  182.         for(i = 0; i < 10; ++ i)
  183.         {
  184.                 n = 1 + (int)(10.0*rand()/(RAND_MAX + 1.0));

  185.                 head = insert_listnode(head, n);
  186.         }

  187.         fdprint_listnode(head);

  188.         printf("\n");

  189.         bkprint_listnode(head);

  190.         printf("\n%d\n", count_listnode(head));

  191.         printf("\n");
  192. #if 10
  193.         head = delete_node(head, 10);
  194.         fdprint_listnode(head);
  195.        printf("\n");

  196.         bkprint_listnode(head);
  197.         printf("\n");
  198. #endif

  199. #if 10
  200.         head = delete_allnode(head, 10);
  201.         fdprint_listnode(head);

  202.         printf("\n");

  203.         bkprint_listnode(head);
  204. #endif

  205.         printf("max = %d\n",max_list(head));
  206.         printf("max = %d\n",min_list(head));
  207.         delete_list(head);

  208.         head = NULL;

  209.         if(head == NULL)
  210.         {
  211.                 printf("ERROR:null pointer!...\n");
  212.         }
  213.         return 0;
  214. }
递归中需要注意的思想我任务就是为了解决当前的问题,我完成最简单的一部操作,其他的由别人去完成,比如汉诺塔中的第一个和尚让第二个和尚把前63个金盘放在B处,而他自己只需要完成从A到C的搬运,实质上他自己完成的只有一部最简答的,但是搬运这种动作有存在非常大的相似性。
 
因此为了解决当前的问题f(n),就需要解决问题f(n-1),而f(n-1)的解决就需要解决f(n-2),这样逐层的分解,分解成很多相似的小事件,当最小的事件解决完成以后,就能解决高层次的事件,这种逐层分解,逐层合并的方式就构成了递归的思想,最主要的要找到递归的出口和递归的方式,搞清楚了这两个,实现一个递归问题相对来说就比较简单啦。
 
但是递归也存在问题,特别是深层次的递归可能导致栈空间的溢出,因为堆栈空间的大小并不是无限大的,特别当递归中数据量特别大的情况下,递归很有可能导致栈空间的溢出,因此递归并不是万能的,但是递归确实是一种思考问题的方式,一种反向思考的形式,从结果到具体的小过程。当然具体的问题就要具体分析啦。
 
用一句简单的话记住递归就是:我完成最简单的那一步,其他的复杂的相似问题都找别人去做吧。
上一篇:linux下so动态库一些不为人知的秘密(上)
下一篇:链表