单链表的快速排序(以升序为例)
1.思想:与顺序表(数组)的快速排序思想相同。
(1)在序列中选择一个数字作为基准temp。
(2)把小于基准数字temp的数字放在temp之前,把大于基准数字temp的数字放在基准数字temp之后。
(3)将序列从temp处分为两段。
(4)两个子序列在分别执行(1)(2)(3)(4),这是一个递归过程。
2.实现:
(1)为了方便操作,选取第一个结点为基准。
(2)选用带头结点的单链表,依次遍历temp后面的结点,将小于temp的结点插入到头节点之后;将大于temp的结点插入到temp之后。
(3)递归调用。
3.代码:
#include <stdio.h>
#include <stdlib.h>
//单链表结点的定义
typedef struct Node{
int data;
struct Node *next;
}NodeType,*LinkList;
/***********函数声明*************/
//生成链表
void Creat_LinkList(int n,LinkList *head,LinkList *tail);
//创建带头节点,有n个结点的单链表
//排序
void Sort(LinkList head,NodeType *tail);
/*参数说明*
@head排序开始的前一个位置
@tail排序的最后一个结点
*/
//输出
void Print(LinkList head);
int main(void){
int n;
printf("请输入序列元素个数:");
scanf("%d",&n);
LinkList head,tail;
Creat_LinkList(n,&head,&tail);
Sort(head,tail);
Print(head);
return 0;
}
//尾插法创建单链表
void Creat_LinkList(int n,LinkList *head,LinkList *tail){
*head=(NodeType *)malloc(sizeof(NodeType));
NodeType *newnode;
*tail=*head;
(*head)->next=NULL;
while(n--){
newnode=(NodeType *)malloc(sizeof(NodeType));
scanf("%d",&(newnode->data));
*tail=(*tail)->next=newnode;
(*tail)->next=NULL;
}
return ;
}
void Sort(LinkList head,NodeType *tail){
//如果除了头节点外,还有一个结点,则不需要排序
//如果仅有头节点,则不需要排序
if(head->next==tail || head==tail)
return ;
NodeType *temp=head->next;
//temp指向基准结点,即第一个(头结点的后一个)结点
NodeType *p=temp->next,*q;
//p和q用来遍历需要排序的结点
NodeType *tail_left,*tail_right;
//tail_left 用来记录temp分开后前半段的尾节点
//tail_right用来记录temp分开后后半段的尾节点
tail_left=head;
tail_right=temp;
//对他们进行初始化
//遍历链表
while(1){
q=p->next;
if(p->data>temp->data){//将大于基准结点的结点用尾插法插入到temp后面
tail_right=tail_right->next=p;
}
else{//将小于基准结点的结点用头插法插入到temp前面
p->next=head->next;
head->next=p;
if(p->next==temp)
tail_left=p;
}
if(p==tail)//遍历完成后,跳出循环
break;
p=q;
}
/****下面这句话很重要****/
tail_right->next=q;//排序好的将子序列连接到主序列中
//分成两段的递归调用
Sort(head,tail_left);
Sort(temp,tail_right);
return ;
}
void Print(LinkList head){
NodeType *curnode=head->next;
while(curnode){
printf("%5d",curnode->data);
curnode=curnode->next;
}
return ;
}