对一个单链表进行逆序排列。

来源:互联网 发布:新理念外语网络教学app 编辑:程序博客网 时间:2024/05/23 07:23
 

对一个单链表进行逆序排列。

 4308人阅读 评论(3) 收藏 举报
 分类:
 

    算法:当建立好一个链表后,指针的方向是固定的,从某种意义上来说只能从head开始,每一个next都是指向下一个,即从左到右,如果要逆序排列,首先很容易想到要访问到尾节点,将其当做新的头结点,然后让它去指向倒数第二个倒数第三个等等。可问题来了,找到新的头结点到时很容易,那如果让它按照倒数第二个,倒数第三个......也就是从右至左的逆序访问呢?毕竟链表里没有哪个指针可以指向反方向的啊,研究了一下午的老谭的算法,终于想通了(在这里小小的膜拜下,确实牛逼!)。逆序的核心算法如下:首先去遍历初始链表,这个比较简单p2=p1;p1=p1->next;(其中p1主要访问下一结点,p2记录p1走过的地方),访问到最后我们就可以找到新的头结点(即这里的尾节点),然后赋值新的指针,newp=newhead=p1;接下来就是算法的经典步骤了,此时p1,newp,newhead都指向最后一个节点,而p2指向倒数第二个节点,立刻使p2->next=null;这样就等于丢掉了最后一个节点,使得p2指向了新的链表的尾节点(此时链表少了一个节点)。这是第一趟的步骤,为了找出规律,继续看第二趟,也就是说继续让p1,p2指向head(head是原链表的头结点,它一直都没有动,以方便每趟的初始化),然后去遍历链表节点,这时又可以找到最后一个节点(原链表的倒数第二个节点),然后又断开它,这时,已经断开了两个节点了,第一趟找到的是新的头结点,那么立刻连接这个第二次丢掉的节点,重新组建新链表,即newp->next=p1,这样这两个节点就连接起来了,可是这样还不够,为了遍历新的链表,得有一个指针啊,还得让newp指针过去,它现在还在新的头结点哪里呢(不用不是浪费了),让它去倒数第二个节点的地方(以方便以后的连接),结合起来就是newp=newp->next=p1;依次这样循环len次即可(len为链表节点数)。代码如下:

[cpp] view plain copy
 print?
  1. #include <stdio.h>  
  2. #include <malloc.h>  
  3. struct stu  
  4. {  
  5.     int num;  
  6.     struct stu *next;  
  7. };  
  8. void main()  
  9. int i;//用以遍历循环  
  10.   int len;//链表长度  
  11.   struct stu *p1,*p2,*head,*newhead,*newp;  
  12.   p1=p2=head=(struct stu*)malloc(sizeof(struct stu));  
  13.   printf("--------输入链表开始----------\n");  
  14.   printf("输入一个节点(输入0则退出):\n");  
  15.   scanf("%3d",&p1->num);  
  16.   len=1;//长度加1  
  17.   while(p1->num!=0)  
  18.   {  
  19.       p1=(struct stu*)malloc(sizeof(struct stu));//p1指向新节点  
  20.       printf("继续输入节点(输入0则退出):\n");  
  21.       scanf("%3d",&p1->num);  
  22.       if (p1->num==0)  
  23.         p2->next=NULL;//只有一个节点  
  24.       else  
  25.       {  
  26.         p2->next=p1;  
  27.         p2=p1;  
  28.         len++;}  
  29.   }  
  30.   printf("---------输出原始链表----------\n");  
  31.   p1=head;//初始化指针用以输出  
  32.   for (i=1;i<=len;i++)  
  33.   {  
  34.       printf("%3d ",p1->num);  
  35.       p1=p1->next;  
  36.   }  
  37.   printf("\n");  
  38.   printf("------对原始链表排序并输出------\n");  
  39.   for (i=1;i<=len;i++)  
  40.   {  
  41.     p1=p2=head;  
  42.     while(p1->next!=NULL)//此循环非常重要,去指向每趟尾节点  
  43.     {p2=p1;  
  44.     p1=p1->next;//此时p1指向最后一个,p2为倒数第二个,注意循环条件  
  45.     }  
  46.     if(i==1)//第一趟时,将尾节点作为新的头结点  
  47.        newhead=newp=p1;  
  48.     else  
  49.         newp=newp->next=p1;//每趟都新加入一个之前链表丢掉的节点  
  50.     p2->next=NULL;//每趟的倒数第二个节的next都指向空,等于切断了倒数第一个节点  
  51.   }  
  52.   //输出逆序后的链表  
  53.   p1=newhead;  
  54.   for (i=1;i<=len;i++)  
  55.   {printf("%4d",p1->num);  
  56.    p1=p1->next;  
  57.   }  
  58.   printf("\n");  
  59. }  


0 0
原创粉丝点击