从数组冒泡排序迁移到链表冒泡排序

  链表是一种常见的数据结构,在启发式搜索中我们常常需要把无序的链表,按照结点包含的元素数量从小到大排列整齐。面对链表排序问题,尤其是在链表节点是一张巨大的表的情况下,传统的交换法显得力不从心,而通过修改指针指向来使链表逻辑序列有序化是主要的解决途径。

从数组冒泡排序迁移到链表冒泡排序_第1张图片

  如何对链表进行排序,可以借鉴我们所熟知的数组冒泡的思想。在数组冒泡中我们通过交换与移动两种操作把最值向后移动,在不同趟的排序中我们只需要维护一个变动的尾部。链表的冒泡思路与数组的冒泡是一致的,只不过具体的操作上有些不同,无论是交换还是移动操作,链表都需要当前节结点,下一个结点,上一个节点的协作,而要操作这些结点,就要有指向他们的三个指针。而操作这么多指针,最怕指歪了,所以分析的时候要仔细考虑所有情况。

  我们首先来看下正常三交换的过程,先做交换:

从数组冒泡排序迁移到链表冒泡排序_第2张图片

  然后是纠正指针:

 从数组冒泡排序迁移到链表冒泡排序_第3张图片

  当然最需要小心的是这种特殊情况,读者可以自己思考一下,处理过程和正常三交换基本相同:

 从数组冒泡排序迁移到链表冒泡排序_第4张图片

  三移动过程也不能大意,尤其是下面两种特殊情况:

 从数组冒泡排序迁移到链表冒泡排序_第5张图片

  另外关于维护一个变动的尾部tail,其实tail的作用是显示边界,tail后边的全是排好序的,不能动。有了tail,每趟排序就知道在哪里终止,而每趟排序又会有一个最值有序,所以tail在不停向前移动,tail自己是不能前移的,好在它前面有个right,所以tail总是跟随right。

从数组冒泡排序迁移到链表冒泡排序_第6张图片

 

最后附上源码:

 1 /***************************************************************  2 程序作者:yin  3 创建日期:2016-2-16  4 程序说明:链表冒泡,与数组冒泡不同的是交换与移动需要三个指针的协  5 作,即三交换与三移动,并且交换与移动过程要验证合法性,防止指针指  6 歪了。程序可做通用修改,替换sort()中节点类型Node与节点的键值data,  7 外部给sort()传指针地址即可使用。  8  ***************************************************************/
 9 /***************************************************************  10 修改作者:yin  11 修改日期:2016-2-17  12 修改说明:  13 1.完善调试显示与注释  14 后续改进:暂无  15  ***************************************************************/
 16 #include<stdio.h>
 17 #include<stdlib.h>
 18 typedef struct NODE  19 {  20     int data;  21     struct NODE * next;  22 }Node;  23 void sort(Node **h)  24 {  25     //操纵*h与head等效
 26     Node* left=NULL;  27     Node* cur=NULL;  28     Node* right=NULL;  29     //每趟冒泡都有一个变动的尾部tail
 30     for(Node* tail=NULL;tail!=(*h)->next;)//(*h)->next指向的是第二元素,当tail指向第二元素整个程序终止
 31  {  32         //每趟冒泡排序的开始点  33         
 34         //printf("此趟冒泡排序开始......\n");//#####调试显示#####  35         //每趟冒泡起点初始化,都是从第一个点开始的 
 36         left=NULL;  37         cur=*h;  38         right=cur->next;  39         while(1)  40  {  41             if(cur->data > right->data)//逆序,三交换 
 42  {  43                 //printf("now exchange (%2d) and (%2d)\n",cur->data,right->data);//#####调试显示#####  44                 //交换
 45                 cur->next=right->next;  46                 right->next=cur;  47                 if(left==NULL) *h=right;  48                 else left->next=right;;  49                 //纠正
 50                 cur=right;  51                 right=right->next;  52                 //printf("after exchange (%2d) and (%2d)\n",cur->data,right->data);//#####调试显示##### 
 53  }  54             if(right->next!=tail)//三移动为下一次做准备
 55  {  56                 if(left!=NULL)    left=left->next;  57                 else              left=cur;  58                 cur=cur->next;  59                 right=right->next;  60  }  61             else break;  62  }  63         
 64         tail=right;    //一个变动的尾部  65         
 66         //每趟冒泡排序的结束点  67         
 68         //#####调试显示#####
 69     /* printf("此趟冒泡排序的结果\n");  70  for(Node *p=*h;p!=NULL;p=p->next)  71  printf("(%2d) ",p->data);  72  printf("\n"); */    
 73  }  74 }  75 int main()  76 {  77     Node *head=NULL;  78     int dataarray[10]={6,9,8,3,10,5,4,7,2,1};  79     
 80     Node*pt=NULL;  81     for(int i=0;i<10;i++)  82  {  83         //开空间,需要引用 stdlib.h
 84         Node *temp=(Node*)malloc(sizeof(Node));  85         temp->data=dataarray[i];  86         temp->next=NULL;  87         //连接
 88         if(i==0)  89  {  90             head=temp;  91             pt=temp;  92  }  93         else
 94  {  95             pt->next=temp;  96             pt=pt->next;  97  }  98  }  99                 printf("--------------------------------------------------------------------\n"); 100                 printf("初始数据序列:\n"); 101                 for(Node *p=head;p!=NULL;p=p->next) 102                     printf("(%2d) ",p->data); 103                 printf("\n"); 104                 printf("--------------------------------------------------------------------\n"); 105     
106     sort(&head);//测试sort
107     
108                 printf("--------------------------------------------------------------------\n"); 109                 printf("链表冒泡结果:\n"); 110                 for(Node *p=head;p!=NULL;p=p->next) 111                     printf("(%2d) ",p->data); 112                 printf("\n"); 113                 printf("--------------------------------------------------------------------\n"); 114 }

 

你可能感兴趣的:(从数组冒泡排序迁移到链表冒泡排序)