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

目录

一、排序的定义

二、内排序方法

三、插入排序

[3.1 直接插入排序](#3.1 直接插入排序)

[3.1 折半插入排序](#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为基准的快速排序过程如下:

五、快速排序实现

cpp 复制代码
#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

cpp 复制代码
#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;
}
相关推荐
鸽鸽程序猿3 分钟前
【算法】【优选算法】宽搜(BFS)中队列的使用
算法·宽度优先·队列
Jackey_Song_Odd3 分钟前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
Watermelo6177 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
乐之者v12 分钟前
leetCode43.字符串相乘
java·数据结构·算法
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神1 小时前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人1 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
半盏茶香1 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
忘梓.2 小时前
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
算法·动态规划
️南城丶北离2 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络