【初阶数据结构题目】38. 快速排序-非递归版本

2024-08-22 06:44

本文主要是介绍【初阶数据结构题目】38. 快速排序-非递归版本,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

非递归版本

非递归版本的快速排序需要借助数据结构:栈

思路:

假设我们初始要排序的数是:5 3 9 6 2 4

经过一轮快速排序后,找到的基准值是6,也就是keyi=3

通过一轮快速排序后,接下来要排序的数是2 3 4 5 6 9


如果left=0,right=5,keyi=3

左区间:[left,keyi-1] [0,2]

右区间:[keyi+1,right] [4,5]

先把右区间的right5入栈,然后把右区间的left4入栈

然后把左区间的right2入栈,然后把左区间的left0入栈


此时栈里面是:0 2 4 5


然后出栈两次,取到left=0,right=2

我们对下标为0-2的数找基准值

找到基准值keyi=0


此时left=0,right=2,keyi=1

左区间:[left,keyi-1] [0,-1] 非有效区间,不入栈

右区间:[keyi+1,right] [1,2]

先把右区间的right2入栈,然后把右区间的left1入栈


此时栈里面是:1 2 4 5


然后出栈两次,取到left=1,right=2

我们对下标为1-2的数找基准值

找到基准值keyi=1


此时left=1,right=2,keyi=1

左区间:[left,keyi-1] [1,0] 非有效区间,不入栈

右区间:[keyi+1,right] [2,2] 非有效区间,不入栈


此时栈里面是:4 5


然后出栈两次,取到left=4,right=5

我们对下标为4-5的数找基准值

找到基准值keyi=4


此时left=4,right=5,keyi=4

左区间:[left,keyi-1] [4,3] 非有效区间,不入栈

右区间:[keyi+1,right] [5,5] 非有效区间,不入栈


此时排完序了,是2 3 4 5 6 9

我们销毁函数栈。

代码实现:

Sort.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include <stdbool.h>
#include <assert.h>//打印
void PrintArr(int* arr, int n);
//非递归版本快排
//--借助数据结构--栈
void QuickSortNonR(int* arr, int left, int right);

Sort.c

#include"Sort.h"//打印
void PrintArr(int* arr, int n)
{for (int i = 0; i < n; i++){printf("%d ", arr[i]);}printf("\n");
}//定义栈的结构
typedef int STDataType;
typedef struct Stack
{STDataType* arr;int capacity;     //栈的空间大小int top;          //栈顶
}ST;//栈的初始化
void STInit(ST* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;
}//栈顶---入数据,出数据
//入数据
void StackPush(ST* ps, STDataType x)
{assert(ps);//1.判断空间是否足够if (ps->capacity == ps->top){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newCapacity;}//空间足够ps->arr[ps->top++] = x;
}//判断栈是否为空
bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}//栈顶出数据
void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));--ps->top;
}//取栈顶元素
STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->arr[ps->top - 1];
}//栈的销毁
void STDestroy(ST* ps)
{assert(ps);if (ps->arr)free(ps->arr);ps->arr = NULL;ps->top = ps->capacity = 0;
}//非递归版本快排
//--借助数据结构--栈
void QuickSortNonR(int* arr, int left, int right)
{ST st;//创建栈STInit(&st);//栈的初始化StackPush(&st, right);//栈顶入数据StackPush(&st, left);//栈顶入数据while (!StackEmpty(&st))//栈不为空就进入循环{//取栈顶元素---取两次int begin = StackTop(&st);StackPop(&st);//栈顶出数据int end = StackTop(&st);StackPop(&st);//栈顶出数据//[begin,end]---找基准值//双指针法int prev = begin;int cur = begin + 1;int keyi = begin;while (cur <= end){if (arr[cur] < arr[keyi] && ++prev != cur)//这里<和<=一样{Swap(&arr[cur], &arr[prev]);}cur++;}Swap(&arr[keyi], &arr[prev]);//上面循环结束说明cur越界了keyi = prev;//根据基准值keyi划分左右区间//左区间:[begin,keyi-1]//右区间:[keyi+1,end]if (keyi + 1 < end){StackPush(&st, end);//右区间入栈StackPush(&st, keyi + 1);//左区间入栈}if (keyi - 1 > begin){StackPush(&st, keyi - 1);//右区间入栈StackPush(&st, begin);//左区间入栈}}STDestroy(&st);//销毁栈
}

test.c

#include"Sort.h"int main()
{int a[] = { 5, 3, 9, 6, 2, 4, 7, 1, 8 };int n = sizeof(a) / sizeof(int);printf("排序前:");PrintArr(a, n);QuickSortNonR(a, 0, n - 1);printf("排序后:");PrintArr(a, n);return 0;
}

这篇关于【初阶数据结构题目】38. 快速排序-非递归版本的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095532

相关文章

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

conda安装GPU版pytorch默认却是cpu版本

《conda安装GPU版pytorch默认却是cpu版本》本文主要介绍了遇到Conda安装PyTorchGPU版本却默认安装CPU的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录一、问题描述二、网上解决方案罗列【此节为反面方案罗列!!!】三、发现的根本原因[独家]3.1 p

Redis指南及6.2.x版本安装过程

《Redis指南及6.2.x版本安装过程》Redis是完全开源免费的,遵守BSD协议,是一个高性能(NOSQL)的key-value数据库,Redis是一个开源的使用ANSIC语言编写、支持网络、... 目录概述Redis特点Redis应用场景缓存缓存分布式会话分布式锁社交网络最新列表Redis各版本介绍旧

IIS 7.0 及更高版本中的 FTP 状态代码

《IIS7.0及更高版本中的FTP状态代码》本文介绍IIS7.0中的FTP状态代码,方便大家在使用iis中发现ftp的问题... 简介尝试使用 FTP 访问运行 Internet Information Services (IIS) 7.0 或更高版本的服务器上的内容时,IIS 将返回指示响应状态的数字代

MybatisX快速生成增删改查的方法示例

《MybatisX快速生成增删改查的方法示例》MybatisX是基于IDEA的MyBatis/MyBatis-Plus开发插件,本文主要介绍了MybatisX快速生成增删改查的方法示例,文中通过示例代... 目录1 安装2 基本功能2.1 XML跳转2.2 代码生成2.2.1 生成.xml中的sql语句头2

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

一文教你Java如何快速构建项目骨架

《一文教你Java如何快速构建项目骨架》在Java项目开发过程中,构建项目骨架是一项繁琐但又基础重要的工作,Java领域有许多代码生成工具可以帮助我们快速完成这一任务,下面就跟随小编一起来了解下... 目录一、代码生成工具概述常用 Java 代码生成工具简介代码生成工具的优势二、使用 MyBATis Gen

Java List排序实例代码详解

《JavaList排序实例代码详解》:本文主要介绍JavaList排序的相关资料,Java排序方法包括自然排序、自定义排序、Lambda简化及多条件排序,实现灵活且代码简洁,文中通过代码介绍的... 目录一、自然排序二、自定义排序规则三、使用 Lambda 表达式简化 Comparator四、多条件排序五、