链表头结点意义
头结点无实际数据,非必需,主要是为了操作的统一与方便而设立的
有头结点后,在第一个数据节点前插入、删除、修改的操作与对其它结点的操作统一了
基于带头结点的链表有了以下排序
链表初始化
typedef struct a
{
int num;
struct a* next;
}s,*List;
List head=NULL;
void Bubble(List);
void Insert(List);
main()
{
int b[10]={9,14,5,3,4,2,8,10,11,6};//默认10个元素
//头结点初始化
List temp = (List)malloc(sizeof(s));
temp->num=0;
temp->next=NULL;
head=temp;
int i;
for(i=0;i<10;i++)
{
List a = (List)malloc(sizeof(s));
a->num=b[i];
a->next=NULL;
temp->next=a;
temp = temp->next;
}
}
一、冒泡排序
比较相邻节点,选出未排序元素中的最大数,并放在末尾
void Bubble(List head)
{
List pre,cur,next,end;//pre前一项 cur当前项 next后一项 end控制循环次数(优化冒泡)
end=NULL;
while(head->next!=end)
{
//初始化三个指针 ; 判断是否到达结束位置 ; 三个指针集体后移
for(pre=head,cur=pre->next,next=cur->next; next!=end; pre=pre->next,cur=cur->next,next=next->next)
{
if(cur->num > next->num) //从小到大
{
pre->next=next;
cur->next=next->next;
next->next=cur;
//此时next变前一项,cur变后一项 交换next cur
List temp=cur; cur=next; next=temp;
}
}
//一轮循环结束 最后一项已经排好 end提前一项 (冒泡原理)
end = cur;
}
}
二、插入排序
需要用两个指针对链表进行遍历,一个指针用于标记待插入的节点(外循环),另一个指针用于寻找插入位置(内循环)
void Insert(List head)
{
List p1,p2,temp,prep1,prep2;
for(p1=head->next->next,prep1=head->next;p1!=NULL;p1=p1->next,prep1=prep1->next)
{
temp=p1; //保存待插入节点
for(p2=head->next,prep2=head ; p2!=p1 ; p2=p2->next,prep2=prep2->next)
{
if(p2->num > p1->num)
{
p1=p1->next;
prep1->next=temp->next;
prep2->next=temp; //插入对应位置
temp->next=p2;
break;
}
}
}
}