理解与应用排序算法(快速排序C实现)

目录

一、排序的定义

二、内排序方法

三、插入排序

3.1 直接插入排序

3.1 折半插入排序

3.1 链表插入排序

四、交换排序

五、起泡排序

六、快速排序


一、排序的定义

稳定排序和非稳定排序

设文件f=(R1......Ri......Rj......Rn)中记录Ri、Rj(i≠j,i、j=1……n)的key相等,即Ki=Kj。

若在排序前Ri领先于Rj,排序后Ri仍领先于Rj,则称这种排序是稳定的,其含义是它没有破坏原本已有序的次序。


内排序和外排序

若待排文件 f 在计算机的内存储器中,且排序过程也在内存中进行,称这种排序为内排序。

若排序中的文件存入外存储器,排序过程借助于内外存数据交换(或归并)来完成,则称这种排序为外排序。

二、内排序方法

各种内排序方法可归纳为以下五类:

(1)插入排序

(2)交换排序

(3)选择排序

(4)归并排序

  ......

三、插入排序

直接插入排序

折半插入排序

链表插入排序

Shell(希尔)排序

……

3.1 直接插入排序

设待排文件f=(R1R2......Rn)相应的key集合为k ={k1k2......kn}。

排序方法

先将文件中的(R1)看成只含一个记录的有序子文件,然后从R2起,逐个将R2至Rn按key插入到当前有序子文件中,最后得到一个有序的文件。插入的过程上是一个key的比较过程,即每插入一个记录时,将其key与当前有序子表中的key进行比较,找到待插入记录的位置后,将其插入即可。

设文件记录的key集合k={50,36,66,76,95,12,25,36}

3.1 折半插入排序

排序算法的T(n)=O(n2),是内排序时耗最高的时间复杂度。

折半插入排序方法

先将(R[1])看成一个子文件,然后依次插入R[2]……R[n]。但在插入R[i]时,子表[R[1]……R[i-1]]已是有序的,查找R[i]在子表中的位置可按折半查找方法进行,从而降低key的比较次数。

3.1 链表插入排序

  设待排序文件f=(R1 R2……Rn),对应的存储结构为单链表结构:

表置为空表,然后依次扫描链表中每个结点,设其指针为p,搜索到p结点在当前子表的适当位置,将其插入。

设含4个记录的链表如图:

四、交换排序

 “起泡”排序(Bubble Sort)

 “快速”排序(Quick Sort)

4.1 起泡排序

设记录key集合k={50,36,66,76,95,12,25,36},排序过程如下:

4.2 快速排序

设记录的key集合k={50,36,66,76,36,12,25,95},每次以集合中第一个key为基准的快速排序过程如下:

五、快速排序实现 

#include <stdio.h>
#include <stdlib.h>

#define N 15

// 函数声明
int quick_sort(int *data, int low, int high);
int partion(int *data, int low, int high);
int compare(const void *p1, const void *p2);

int main(int argc, char *argv[])
{
    int i;
    int data[N] = {0};

    // 使用种子值10初始化随机数生成器
    srandom(10);

    // 生成随机数组
    for(i = 0; i < N; i++){
        data[i] = random() % 100;    
    }

    // 打印原始数组
    for(i = 0; i < N; i++){
        printf("%d ", data[i]);
    }
    puts("");

    // 调用快速排序算法对数组进行排序
    quick_sort(data, 0, N-1);

    // 打印排序后的数组
    for(i = 0; i < N; i++){
        printf("%d ", data[i]);
    }
    puts("");

    return 0;
}

// 快速排序的分区函数
int partion(int *data, int low, int high){
    int temp = data[low];

    while(low < high){
        // 从右向左找到第一个比基准值小的元素
        while(low < high && temp <= data[high]){
            high--;
        }
        // 将比基准值小的元素移到左边
        data[low] = data[high];

        // 从左向右找到第一个比基准值大的元素
        while(low < high && temp >= data[low]){
            low++;
        }
        // 将比基准值大的元素移到右边
        data[high] = data[low];
    }
    
    // 将基准值放置到最终位置
    data[low] = temp;

    return low;
}

// 快速排序函数
int quick_sort(int *data, int low, int high){
    int t;

    // 检查输入数组是否为空
    if(data == NULL){
        return -1;
    }

    // 递归结束条件
    if(high <= low){
        return 0;
    }

    // 分区,并获取基准值的位置
    t = partion(data, low, high);
    // 对基准值左边的子数组进行递归排序
    quick_sort(data, low, t-1);
    // 对基准值右边的子数组进行递归排序
    quick_sort(data, t+1, high);

    return 0;
}

// 比较函数,用于qsort函数的排序
int compare(const void *p1, const void *p2){
    return (*(const int *)p1 - *(const int *)p2);
}

注意:

1、compare函数是为qsort函数准备的,但在这个示例中并未使用qsort。
2、quick_sort函数返回了0,但在实际应用中,我们通常不需要这个返回值,因为排序函数主要是修改数组的内容。但是,检查数组是否为空并返回-1是一个好的做法,可以捕获潜在的错误。

六、快速排序测试题

1、利用快速排序对以下数据进行排序1,5,7,8,3,5,9,4,1,0

#include <stdio.h>
#include <stdlib.h>

int	quick_sort(int *data, int low, int high);
int partion(int *data, int low, int high);

int main(int argc, char *argv[])
{
	int data[] = {1, 5, 7, 8, 3, 5, 9, 4, 1, 0};
	int i;

	for(i = 0; i < 10; i++){
		printf("%d ", data[i]);
	}
	puts("");

	quick_sort(data, 0, 9);

	for(i = 0; i < 10; i++){
		printf("%d ", data[i]);
	}
	puts("");
	return 0;
}

int partion(int *data, int low, int high){
	int temp = data[low];

	while(low < high){
		while(low < high && temp <= data[high]){
			high--;
		}
		data[low] = data[high];
		while(low < high && temp >= data[low]){
			low++;
		}
		data[high] = data[low];
	}

	data[low] = temp;

	return data[low];
}

int	quick_sort(int *data, int low, int high){
	int t;

	if(data == NULL){
		return -1;
	}	

	if(low >= high){
		return 0;
	}

	t = partion(data, low, high);
	quick_sort(data, low, t-1);
	quick_sort(data, t+1, high);

	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/675328.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TMS320F280049 ECAP模块--应用(2)

例1-上升沿触发 如下图所示&#xff0c;evt1-4设置为上升沿触发&#xff0c;在每个上升沿ctr值依次加载到cap1-4. 例2-上升下降沿触发 每个边沿都可选为事件&#xff0c;每次事件到来&#xff0c;依次把ctr加载到cap1-4。 例3-差异模式下上升沿触发 差异模式下每次事件到来时…

varchar 字段扩展问题

背景 近期接到一个产品需求&#xff0c;由于上游业务字段扩大了字段&#xff0c;下游的字段也得跟着调整扩大&#xff0c;这就涉及几十张大表&#xff0c;十几亿行数据的变更。 如果按照传统方式 onlie-ddl 借用第三方工具也得三四天分批跑&#xff0c;看了看MySQL官网&#…

ctfshow-web入门-爆破(web25)及php_mt_seed工具的安装与使用

爆个&#x1f528;&#xff0c;不爆了 hexdec() 函数用于将十六进制字符串转换为十进制数&#xff1b; 注意&#xff1a; 我最开始做这道题时看错了&#xff0c;误以为随机数的种子直接来自于 flag 的前八位&#xff0c;以为就是 ctfshow{ 这八个字符然后 md5 加密再截取&a…

使用jquery.mousewheel-3.0.6.pack.js时报错

基于1.12.4版本的jquery.min.js&#xff0c;在使用jquery.mousewheel-3.0.6.pack.js时报错了&#xff1a; 可以如下解决&#xff1a; addEventListener事件里要加上{ passive: false }&#xff0c;这样就可以在使用鼠标滚轮放大缩小图片时&#xff0c;就不会报上述的错误了。 …

VsQt单元测试目录的管理方式

正常项目的文件管理方式 正常项目的目录&#xff0c;是由文件系统中实际的文件夹进行分类管理的。 但是如果单元测试用实际文件夹管理的话&#xff0c;会出现问题&#xff0c;就是被测类太多了&#xff0c;用文件系统管理的话&#xff0c;不太方面查看&#xff0c;如下图所示。…

7EPhone云手机各功能详解

上篇文章详细介绍了7EPhone云手机的注册和购买&#xff08;没看到的同学可以自主去翻看一下哈~&#xff09;&#xff0c;这篇文章主要给大家讲解7EPhone作为专业海外社媒营销工具&#xff0c;界面上显示什么信息&#xff0c;云机到底有什么功能&#xff0c;这些功能具体怎么来使…

招聘兼职发布客服的骗局大揭秘

在现今的互联网社会中&#xff0c;线上兼职成为许多人追求额外收入或灵活就业的方式。然而&#xff0c;这其中也隐藏着不少骗局&#xff0c;在各大招聘网站或者招聘软件上的今日头条兼职客服招聘就是其中之一。本文将详细揭露这种骗局的运作方式&#xff0c;以帮助大家识别和防…

对比WPF和Avalonia的边框渲染差异

众所周知&#xff0c;诸如Border、Rectangle等元素&#xff0c;是具有边框的。但在WPF和Avalonia中&#xff0c;边框的渲染机制有所不同。 如下代码&#xff0c;Border的边框和背景色均为黑色&#xff0c;并且将透明度设为0.5&#xff1a; <Border Width"100" H…

知了汇智携手数字经济商会,共促物联网鸿蒙产教融合新篇章

5月31日&#xff0c;由成都市数字经济商会主办&#xff0c;华为技术有限公司协办&#xff0c;成都知了汇智科技有限公司及成都市数字经济商会人才专委会共同承办的“产教融合物联网鸿蒙人才交流”大会在成都天府软件园产教融合基地隆重举办。 会议旨在加速四川省鸿蒙技术产业的…

Transformer详解(3-1)-attention为什么要除以根号d

attention的计算公式&#xff0c;为什么要除以根号d? 参考 NLP面试官&#xff1a;“Attention为什么要除以根号d” 算法女生这么回答当场想发 offer

【轻触按键】终篇 -- 纯硬 VS 复合

1、选型 2、开关机电路–填坑1 3、开关机电路–填坑1.a 4、开关机电路–复合芯片解决方案 填坑2 总结 上述几篇&#xff0c;基本上都是比较靠谱的硬件方案&#xff1b; ①所有开关均关闭&#xff1b; X1灯亮&#xff1b;P-MOS 管Q1关断&#xff1b; 特别注意&#xff0c;…

每日两题 / 34. 在排序数组中查找元素的第一个和最后一个位置 33. 搜索旋转排序数组(LeetCode热题100)

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣&#xff08;LeetCode&#xff09; 根据二分函数&#xff0c;得到>target和<target的两个&#xff0c;分别是答案的l和r class Solution { public:vector<int> searchRange(vector<int>& nums,…

简单聊下服务器防病毒

在当今数字化时代&#xff0c;服务器作为数据存储、处理与传输的核心设备&#xff0c;其安全性显得尤为关键。服务器防病毒工作&#xff0c;不仅是保障企业信息安全的重要一环&#xff0c;更是维护用户数据隐私的关键举措。以下&#xff0c;我们将从多个方面&#xff0c;简单探…

spring boot +Scheduled 动态定时任务配置

通常情况下我们设定的定时任务都是固定的,有时候需要我们动态的配置定时任务,下面看代码 import com.mybatisflex.core.query.QueryWrapper; import com.yzsec.dsg.web.modules.exportpwd.entity.ExportPwd; import com.yzsec.dsg.web.modules.exportpwd.entity.table.Export…

04C编译过程/32位,64位区别/断言/位域...

C零碎语法 目录 文章目录 C零碎语法1.编译过程1.2 编译1.3 汇编1.4 链接 2.不同位机器&#xff0c;各数据类型所占位数3.assert() 断言&#xff08;宏&#xff09;3.1缺点3.2解决办法3.3使用举例3.3.1函数开始处检验传入参数的合法性 4.位域4.1举例4.2补充 5.typedef/define(…

Android11 AudioTrack和Track建立联系

应用程序创建AudioTrack时&#xff0c;导致AudioFlinger在播放线程中&#xff0c;创建Track和其对应。那它们之间是通过什么来建立联系传递数据的&#xff1f;答案是共享内存。 创建Track时&#xff0c;导致其父类TrackBase的构造函数被调用 //frameworks/av/services/audiofl…

网络原理——HTTP/HTTPS ---- HTTPS

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 目录 HTTPS加密与解密HTTPS的工作流程使用对称密钥来加密使用非对称密钥 来对 对称密钥进行加密第三方公证总结 HTTPS https本质上就是在http的基础之上 增加了加密层,抛开加密层之后,剩下的部…

USART串口外设

USART介绍 USART&#xff1a;另外我们经常还会遇到串口&#xff0c;叫UART&#xff0c;少了个S&#xff0c;就是通用异步收发器&#xff0c;一般我们串口很少使用这个同步功能&#xff0c;所以USART和UART使用起来&#xff0c;也没有什么区别。 其实这个STM32的USART同步模式&a…

抖店入驻门槛,一降再降,2024年商家入驻抖店最佳的时机来了!

大家好&#xff0c;我是电商糖果 抖店已经发展有四年多的时间了&#xff0c;现在也算是比较成熟的电商平台. 这几年因为直播带货的火爆&#xff0c;再加上抖音的流量支撑&#xff0c;还有抖音在背后的扶持和推广。 让抖店成了电商行业的黑马项目&#xff0c;吸引了不少商家入…

融合通信项目中常见设备有哪些?

在信息化时代的今天&#xff0c;人们对于通讯的需求越来越大&#xff0c;而传统的单一通讯方式已经无法满足现代社会的需要。因此&#xff0c;融合通信系统的出现成为了必然趋势。 融合通信系统对行业发展的作用不仅仅是提高通信效率和降低通信成本&#xff0c;还可以提升管理效…