DAY8,写一个双向链表的快速排序函数

题目

写一个双向链表的快速排序函数

思路

/* 递归 大致思路

递进阶段:

以基准,将数据分成'大于基准'和'小于基准'的两份(单次快排);

对'基准左边'重复上述操作;

函数出口:'基准左边'只有一个数

回归阶段:返回到上一层(类似二叉树的构建,左子树)

递进阶段:

对'基准右边'重复上述操作;

函数出口:'基准左边'只有一个数

回归阶段:返回到上一层(类似二叉树的构建,右子树)

*/

代码

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);

效果

相关推荐
WeiLai111229 分钟前
面试基础--Redis 缓存穿透、缓存击穿、缓存雪崩深度解析
java·redis·分布式·后端·缓存·面试·架构
wclass-zhengge29 分钟前
02C#基本结构篇(D1_基本语法)
开发语言·microsoft·c#
zctel30 分钟前
java中小型公司面试预习资料(二):Redis
java·redis·面试
hrrrrb30 分钟前
【C语言】数组篇
c语言·开发语言
爱吃烤鸡翅的酸菜鱼1 小时前
Java【网络原理】(3)网络编程续
java·运维·服务器·网络
蜡笔小新..3 小时前
R语言和RStudio安装
开发语言·r语言
ALPH_3 小时前
R语言的基础命令及实例操作
开发语言·数据分析·r语言·perl·r语言-4.2.1
咩咩觉主3 小时前
C# &Unity 唐老狮 No.6 模拟面试题
开发语言·unity·面试·c#·游戏引擎·唐老师
╰つ゛木槿5 小时前
Spring Boot 调用DeepSeek API的详细教程
java·spring boot·后端·deepseek
*.✧屠苏隐遥(ノ◕ヮ◕)ノ*.✧5 小时前
C语言_数据结构总结8:链式队列
c语言·开发语言·数据结构·链表·visualstudio·visual studio