数据结构65:快速排序算法(QSort,快排)
C语言中自带函数库中就有快速排序——qsort函数 ,包含在 <stdlib.h> 头文件中。
快速排序算法是在起泡排序的基础上进行改进的一种算法,其实现的基本思想是:通过一次排序将整个无序表分成相互独立的两部分,其中一部分中的数据都比另一部分中包含的数据的值小,然后继续沿用此方法分别对两部分进行同样的操作,直到每一个小部分不可再分,所得到的整个序列就成为了有序序列。
例如,对无序表{49,38,65,97,76,13,27,49}
进行快速排序,大致过程为:
- 首先从表中选取一个记录的关键字作为分割点(称为“枢轴”或者支点,一般选择第一个关键字),例如选取 49;
- 将表格中大于 49 个放置于 49 的右侧,小于 49 的放置于 49 的左侧,假设完成后的无序表为:
{27,38,13,49,65,97,76,49}
; - 以 49 为支点,将整个无序表分割成了两个部分,分别为
{27,38,13}
和{65,97,76,49}
,继续采用此种方法分别对两个子表进行排序; - 前部分子表以 27 为支点,排序后的子表为
{13,27,38}
,此部分已经有序;后部分子表以 65 为支点,排序后的子表为{49,65,97,76}
; - 此时前半部分子表中的数据已完成排序;后部分子表继续以 65为支点,将其分割为
{49}
和{97,76}
,前者不需排序,后者排序后的结果为{76,97}
; - 通过以上几步的排序,最后由子表
{13,27,38}
、{49}
、{49}
、{65}
、{76,97}
构成有序表:{13,27,38,49,49,65,76,97}
;
整个过程中最重要的是实现第 2 步的分割操作,具体实现过程为:
- 设置两个指针 low 和 high,分别指向无序表的表头和表尾,如下图所示:
- 先由 high 指针从右往左依次遍历,直到找到一个比 49 小的关键字,所以 high 指针走到 27 的地方停止。找到之后将该关键字同 low 指向的关键字进行互换:
- 然后指针 low 从左往右依次遍历,直到找到一个比 49 大的关键字为止,所以 low 指针走到 65 的地方停止。同样找到后同 high 指向的关键字进行互换:
- 指针 high 继续左移,到 13 所在的位置停止(13<49),然后同 low 指向的关键字进行互换:
- 指针 low 继续右移,到 97 所在的位置停止(97>49),然后同 high 指向的关键字互换位置:
- 指针 high 继续左移,此时两指针相遇,整个过程结束;
该操作过程的具体实现代码为:
#define MAX 8
typedef struct
{
int key;
}SqNote; typedef struct
{
SqNote r[MAX];
int length;
}SqList;
//交换两个记录的位置
void swap(SqNote *a, SqNote *b)
{
int key = a->key;
a->key = b->key;
b->key = key;
}
// 快速排序,分割的过程
int Partition(SqList *L, int low, int high)
{
int pivotkey = L->r[low].key;
// 直到两指针相遇,程序结束
while (low < high)
{
// high指针左移,直至遇到比pivotkey值小的记录,指针停止移动
while (low<high && L->r[high].key>=pivotkey)
{
high--;
}
// 交换两指针指向的记录
swap(&(L->r[low]), &(L->r[high]));
// low 指针右移,直至遇到比pivotkey值大的记录,指针停止移动
while (low<high && L->r[low].key<=pivotkey)
{
low++;
}
// 交换两指针指向的记录
swap(&(L->r[low]), &(L->r[high]));
}
return low;
}
该方法其实还有可以改进的地方:在上边实现分割的过程中,每次交换都将支点记录的值进行移动,而实际上只需在整个过程结束后(low==high),两指针指向的位置就是支点记录的准确位置,所以无需每次都移动支点的位置,最后移动至正确的位置即可。
所以上边的算法还可以改写为:
// 此方法中,存储记录的数组中,下标为 0 的位置时空着的,不放任何记录,记录从下标为 1 处开始依次存放
int Partition(SqList *L, int low, int high)
{
L->r[] = L->r[low];
int pivotkey = L->r[low].key;
// 直到两指针相遇,程序结束
while (low<high)
{
// high指针左移,直至遇到比pivotkey值小的记录,指针停止移动
while (low<high && L->r[high].key>=pivotkey)
{
high--;
}
// 直接将high指向的小于支点的记录移动到low指针的位置。
L->r[low] = L->r[high];
// low 指针右移,直至遇到比pivotkey值大的记录,指针停止移动
while (low<high && L->r[low].key<=pivotkey)
{
low++;
}
// 直接将low指向的大于支点的记录移动到high指针的位置
L->r[high] = L->r[low];
}
// 将支点添加到准确的位置
L->r[low] = L->r[];
return low;
}
快速排序的完整实现代码
#include <stdio.h>
#include <stdlib.h>
#define MAX 9 // 单个记录的结构体
typedef struct
{
int key;
}SqNote;
// 记录表的结构体
typedef struct
{
SqNote r[MAX];
int length;
}SqList;
// 此方法中,存储记录的数组中,下标为 0 的位置时空着的,不放任何记录,记录从下标为 1 处开始依次存放
int Partition(SqList *L, int low, int high)
{
L->r[] = L->r[low];
int pivotkey = L->r[low].key;
// 直到两指针相遇,程序结束
while (low<high)
{
// high指针左移,直至遇到比pivotkey值小的记录,指针停止移动
while (low<high && L->r[high].key>=pivotkey)
{
high--;
}
// 直接将high指向的小于支点的记录移动到low指针的位置。
L->r[low] = L->r[high];
// low 指针右移,直至遇到比pivotkey值大的记录,指针停止移动
while (low<high && L->r[low].key<=pivotkey)
{
low++;
}
// 直接将low指向的大于支点的记录移动到high指针的位置
L->r[high] = L->r[low];
}
// 将支点添加到准确的位置
L->r[low] = L->r[];
return low;
}
void QSort(SqList *L, int low, int high)
{
if (low<high)
{
// 找到支点的位置
int pivotloc = Partition(L, low, high);
// 对支点左侧的子表进行排序
QSort(L, low, pivotloc-);
// 对支点右侧的子表进行排序
QSort(L, pivotloc+, high);
}
}
void QuickSort(SqList *L)
{
QSort(L, , L->length);
}
int main()
{
SqList *L = (SqList*)malloc(sizeof(SqList));
L->length = ;
L->r[].key = ;
L->r[].key = ;
L->r[].key = ;
L->r[].key = ;
L->r[].key = ;
L->r[].key = ;
L->r[].key = ;
L->r[].key = ;
QuickSort(L);
for (int i=; i<=L->length; i++)
{
printf("%d ", L->r[i].key);
}
return ;
}
运行结果:
总结
快速排序算法的时间复杂度为O(nlogn)
,是所有时间复杂度相同的排序方法中性能最好的排序算法。
数据结构65:快速排序算法(QSort,快排)的更多相关文章
- 快速排序c++实现 快排C++代码实现
快速排序c++实现 快排C++ 第一.算法描述 快速排序由C. A. R. Hoare在1962年提出,该算法是目前实践中使用最频繁,实用高效的最好排序算法, 快速排序算法是采用分治思想的算法,算法分 ...
- qsort 快排函数(C语言)
qsort 快排函数(C语言) 函数原型 void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, ...
- poj1007 qsort快排
这道题比较简单,但通过这个题我学会了使用c++内置的qsort函数用法,收获还是很大的! 首先简要介绍一下qsort函数. 1.它是快速排序,所以就是不稳定的.(不稳定意思就是张三.李四成绩都是90, ...
- JS算法之快排&冒泡
1.快速排序思想: 1.1 先找数组的最中间的一个数为基准 1.2 把数组通过此基准分为小于基准的left数组和大于基准的right数组, 1.3 递归重复上面的两个步骤, 代码如下: functio ...
- 如何用快排思想在O(n)内查找第K大元素--极客时间王争《数据结构和算法之美》
前言 半年前在极客时间订阅了王争的<数据结构和算法之美>,现在决定认真去看看.看到如何用快排思想在O(n)内查找第K大元素这一章节时发现王争对归并和快排的理解非常透彻,讲得也非常好,所以想 ...
- 排序算法C语言实现——冒泡、快排、堆排对比
对冒泡.快排.堆排这3个算法做了验证,结果分析如下: 一.结果分析 时间消耗:快排 < 堆排 < 冒泡. 空间消耗:冒泡O(1) = 堆排O(1) < 快排O(logn)~O(n) ...
- 快速排序详解(lomuto划分快排,hoare划分快排,classic经典快排,dualpivot双轴快排源码)
目录 快速排序(lomuto划分快排,hoare划分快排,classic经典快排,dualpivot双轴快排) 一.快速排序思想 二.划分思想 三.测试用例 快速排序(lomuto划分快排,hoare ...
- 快排 快速排序 qsort quicksort C语言
现在网上搜到的快排和我以前打的不太一样,感觉有点复杂,我用的快排是FreePascal里/demo/text/qsort.pp的风格,感觉特别简洁. #include<stdio.h> # ...
- javascript高级排序算法之快速排序(快排)
javascript高级排序算法之快速排序(快排)我们之前讨论了javascript基本排序算法 冒泡排序 选择排序 插入排序 简单复习: 冒泡排序: 比较相邻的两个元素,如果前一个比后一个大,则交换 ...
随机推荐
- svn服务,svnserve开机启动
在服务器(我的环境是centos6.5)上部署完svn之后,一般都希望每次重启的时候svn服务能够随着启动.上网搜索了一下,一般有两种做法: 一.启动脚本+/etc/rc.local启动 1. 在某个 ...
- Spring 注解 整理
首先 在xml中配置 xmlns:context="http://www.springframework.org/schema/context" http://www.spring ...
- JS中变量和常量的定义
var只能声明一个变量,这个变量可以保存任何数据类型的值 ES6之前并没有定义声明常量的方式,ES6标准中引入了新的关键字const来定义常量 使用const定义常量后,常量无法改变 const a= ...
- Error creating bean with name 'as' defined in class path resource
(1)一个是setter方法的名字和配置文件对应名字有问题 (2)导入的包不对,搭建环境出错.
- CodeForces 681D Gifts by the List (树上DFS)
题意:一个家庭聚会,每个人都想送出礼物,送礼规则是, 一个人,先看名单列表,发现第一个祖先 就会送给他礼物,然后就不送了,如果他没找到礼物 他会伤心的离开聚会!告诉你m个祖先关系, 和每个人想给谁送! ...
- APUE(5)---标准I/O库 (1)
一.引言 标准I/O库不仅是UNIX,许多i其他操作系统都实现了标准I/O库,所以这个库由ISO C标准说明.标准I/O库处理很多细节,如缓冲区分配,以及优化的块长度执行I/O等.这使得它便于用户使用 ...
- Discovering Gold LightOJ - 1030 (概率dp)
You are in a cave, a long cave! The cave can be represented by a 1 x N grid. Each cell of the cave c ...
- redis整理の配置
redis有一个很强大也很重要的配置文件redis.conf.此文件可以随服务启动,为服务配置各种不同场景所需的参数: daemonize: 默认情况下,redis 不是在后台运行的,如果需要在后台运 ...
- 20145218张晓涵_Web基础
20145218张晓涵_Web基础 基础知识 Apache一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广泛使用,是最流行的Web服务器端软件之一.它快速.可靠并且 ...
- Arcgis Android 手动搭建开发环境
前言 本文为大家分享arcgis android 环境的手动搭建过程,默认你懂一定的java和android 基础知识,已经有android的开发环境.如缺乏以上环境和知识,请自行补充. 版本介绍 A ...