在大一上学期,我们学了冒泡排序,选择排序,插入排序等等,而今天主要详解一下链表的冒泡排序的问题。(边看代码,边讲解)
首先,回顾一下,什么叫做冒泡排序。冒泡排序是一种时间复杂度在n的平方下的排序;每次循环都是比较前后两项,要么以从小到大排序,要么从大到小排序。
第一种:
struct node *bubblesort(struct node *headptr)//接受头指针,链表的开端,首节点不为空的链表
struct node *pre=NULL,*flag=NULL,*head=*headptr,*temp;//pre代表前一个指针,flag用作循环变量,很重要
int num;//循环变量
while(*head!=flag)
{
num=0;
while(*(head->nextptr)!=flag){
if(*head->num<*(head->nextptr)->num{//循环比较相邻两个的大小,按从大到小的排序
*temp=*(head->nextptr);//将所指向的第二指针头存储
*(head->nextptr)=*(head->nextptr->nextptr);//将第三指针头接在第一指针头的后面
*temp->nextptr=*head;//将第一指针头放在第二指针的后面
if(num>0)//便于将pre时候是空指针给分开
*pre->nextptr=*temp;
*pre=*temp;//移动pre,向后移一位
if(num==0)//若是头指针,将改变headptr,链表的头指针
*headptr=*temp;
}
else{//若不满足大小关系。两者都往移一位
*pre=*head;
*head=*(head->nextptr);
}
num++;//方便pre的问题
}
*flag=*head;将flag每次都往前移一位,使次数尽量保证少
*head=*headptr;//将head重新改为headptr链表头
}
return *headptr;//返回排好序的链表
第二种
struct node *bubblesort(struct node *head)//首节点为空的链表
{
struct node *pre,*p,*tail,*headptr=*head;;
*tail=NULL;//循环变量
while(*headptr!=*tail)//控制循环变量
{
*pre=*headptr;//前指针的赋值
*p=*(headptr->nextptr);
while(*(p->nextptr)!=*tail)
{
if(p->num<p->nextptr->num){//前一个小于后一个
pre->nextptr=p->nextptr;
p->nextptr=p->nextptr->nextptr;
pre->nextptr->nextptr=p;//这个地方我觉得很好
}
else{
*p=*(p->nextptr);
*pre=*(pre->nextptr);
}
}
*tail=*p;//将结束指针往前移一位
}
return *headptr;//返回排好序的链表
总结:两者稍有不同,但是最关键的地方都是循环的条件的控制;第一种在head!=flag的条件下运行,而第二个其实是一样的,认识清楚链表的指针改变很为重要,不然很可能出现
运行时的的错误。在本代码中,我觉得pre->nextptr-nextptr是一个非常好的地方,毕竟链表是一个类似于许多长条磁体连在一起的模型,抓住一个节点,可以往前或者往后表示其他的节点。