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

效果

相关推荐
忘忧人生13 分钟前
docker 部署 java 项目详解
java·docker·容器
null or notnull41 分钟前
idea对jar包内容进行反编译
java·ide·intellij-idea·jar
Eiceblue1 小时前
Python 合并 Excel 单元格
开发语言·vscode·python·pycharm·excel
言午coding2 小时前
【性能优化专题系列】利用CompletableFuture优化多接口调用场景下的性能
java·性能优化
SomeB1oody2 小时前
【Rust自学】15.2. Deref trait Pt.1:什么是Deref、解引用运算符*与实现Deref trait
开发语言·后端·rust
缘友一世2 小时前
JAVA设计模式:依赖倒转原则(DIP)在Spring框架中的实践体现
java·spring·依赖倒置原则
何中应3 小时前
从管道符到Java编程
java·spring boot·后端
SummerGao.3 小时前
springboot 调用 c++生成的so库文件
java·c++·.so
情深不寿3173 小时前
C++----STL(list)
开发语言·c++
组合缺一3 小时前
Solon Cloud Gateway 开发:Route 的过滤器与定制
java·后端·gateway·reactor·solon