题目
写一个双向链表的快速排序函数
思路
/* 递归 大致思路
递进阶段:
以基准,将数据分成'大于基准'和'小于基准'的两份(单次快排);
对'基准左边'重复上述操作;
函数出口:'基准左边'只有一个数
回归阶段:返回到上一层(类似二叉树的构建,左子树)
递进阶段:
对'基准右边'重复上述操作;
函数出口:'基准左边'只有一个数
回归阶段:返回到上一层(类似二叉树的构建,右子树)
*/
代码
link.c文件
#include "link.h"
void SortData(const linklistPtr lift,const linklistPtr right)
{
//检测地址合法,应考虑链表为空情况?
//函数出口
if(lift==right||lift==NULL||right==NULL){return;} //指向同一个节点,或则,说明排序完毕
//运行到此,说明链表需要排序,准备指针,用于遍历比较
linklistPtr head=lift; //复制头指针
linklistPtr tail=right; //复制尾指针
//进行一次快排
DataType index=head->data; //选定基准
while(1)
{
//基准与右边比较
while(index<=tail->data&&head!=tail) //比基准大,放右边不动,继续向左偏移,判断下一个数据
{
tail=tail->prev; //向左偏移
}
if(head==tail){break;} //如果是因为head==tail而退出的循环,则无需再交换数据,直接退出
head->data=tail->data; //因为值比基准小而退出,此值应该放在左边 当前head指向的节点
head=head->next; //继续向左偏移
//轮到基准与左边比较
while(index>=head->data&&head!=tail)
{
head=head->next; //继续向左偏移
}
if(head==tail){break;} //如果是因为head==tail而退出的循环,则无需再交换数据,直接退出
tail->data=head->data; //因为值比基准大而退出,大值应该放在右边 当前tail指向的节点
tail=tail->prev;
}
printf("tips:单次快排完成,已退出循环\n");
//运行到次,说明head==tail,一次快排完成,将基准放入tail节点
tail->data=index;
//递进阶段
SortData(lift,tail->prev); //以基准为界,将数分成左半边和右半;分别排序
SortData(tail->next,right); //当tail为 ligt---right 首位时,next prev可能传入NULL?
}
linklistPtr CreatLinkList(void)
{
//堆区申请
linklistPtr H=(linklistPtr)malloc(sizeof(linklist));
if(NULL==H){return NULL;}
//头节点指针域 赋值 初始值
H->next=NULL;
H->prev=NULL;
//头节点数据域 赋值 初始值
H->tail=H;
return H;
}
//申请节点 封装数据
linklistPtr CreatNode(DataType e)
{
//堆区申请
linklistPtr newnode=(linklistPtr)malloc(sizeof(linklist));
if(NULL==newnode){return NULL;}
//普通节点指针域 赋值 初始值
newnode->next=NULL;
newnode->prev=NULL;
//普通节点数据域 赋值 初始值
newnode->data=e;
return newnode;
}
void AddData(linklistPtr H,DataType e)
{
linklistPtr newnode=CreatNode(e);
if(NULL==newnode||NULL==H){return;}
//本节点处理
newnode->prev=H->tail;//本节点上一个节点,应为 原来的尾节点
//上一个节点处理
H->tail->next=newnode;//原尾节点,下一个节点,为本节点;;上一个节点不变
//尾指针 指向 本节点
H->tail=newnode;
}
void ShowData(const linklistPtr H)
{
if(NULL==H){return;}
linklistPtr temp=H;
printf("tips:当前链表中数据为:");
while(temp->next!=NULL) //下一个节点不为空
{
temp=temp->next; //成为下一个节点
printf("%d ",temp->data); //输出节点内容
}
printf("\n\n");
}
main.c文件
#include "link.h"
int main(int argc, const char *argv[])
{
//创建链表 头节点
linklistPtr H=CreatLinkList();
//手动添加数据
AddData(H,1);
AddData(H,3);
AddData(H,5);
AddData(H,7);
AddData(H,9);
AddData(H,2);
AddData(H,4);
AddData(H,6);
AddData(H,8);
AddData(H,0);
//显示当前链表上数据
ShowData(H);
//快速排序
SortData(H->next,H->tail);
ShowData(H);
return 0;
}
link.h文件
typedef int DataType;
typedef struct linklist
{
struct
{
DataType data; //普通节点数据域
struct linklist *tail; //头节点数据域
};
struct linklist *next; //指针域,指向下一个节点
struct linklist *prev; //指针域,指针上一个节点
}linklist,*linklistPtr;
void TextInit(const char* ch); //文件初始化
linklistPtr CreatLinkList(void); //创建头节点
linklistPtr CreatNode(DataType e); //申请节点 封装数据
void AddData(linklistPtr H,DataType e); //添加数据
void ShowData(const linklistPtr H); //显示链表上的数据
void SortData(const linklistPtr lift,const linklistPtr right);
效果