快排算法
- 一、快速排序
- 1.1 快排概念
- 1.2 快排算法基本思想
- 1.3 快排算法具体说明
- 1.4 通过快排举例进行详解
- 二、代码实现
- 三、结果展示
一、快速排序
1.1 快排概念
快速排序是冒泡排序的优化,是一种基于交换的排序方式。
时间复杂度 O(nlogn)。
1.2 快排算法基本思想
分而治之思想
通过一趟排序,将待排序列分成两部分,
其中一部分中的数据都比另一部分中的数据小(每一部分中的数据无需保证有序)。
然后将分成的这两部分数据,每一个部分分别在各自执行排序,每一部分再分成独立的两部分。
将上面的方式通过递归执行,直到整个序列有序。
1.3 快排算法具体说明
在一串待排序序列的数列中,通过找一个关键字(待排序序列中的一个数据元素),从而将待排序序列分为两部分(一部分都大于这个关键字,一部分都小于这个关键字),但这两部分序列无需是有序的。
以上操作本质就是找到关键字在这个序列中(升序或降序)该存在的位置。
然后被这个关键字分割的两部分序列继续按照上述描述进行分割(递归思想)。
综合来说将算法思路分成三个部分:
1.挑元素
2.划分组
3.分组重复前两步
1.4 通过快排举例进行详解
以无序序列 8,4,13,67,99,23,15为例:
1.挑元素:
一般是以序列首元素为作为参考元素(关键字),首元素是8。
2.划分组:
本质是确定参考元素(关键字) 8 该存在的位置,并将序列分为两个部分。
将大于 8 的数据放到 8 应该存在位置的右侧,
将小于 8 的数据放到 8 应该存在位置的左侧,
且被 8 分成两部分的序列无需是有序的。
首先,找出 8 应该存放至序列本应存在的位置
定义一个temp,将数据 8 赋给temp
定义i,j变量分别记录序列的第一个元素,和最后一个元素的位置
以上述无序序列为例i=0,j=6
从j位置上开始和temp进行循环比较,如果是s[j]>temp且i<j,则进行j- -
如果是s[j]<=temp则循环结束
j位置上的元素要赋值到i位置的元素上
i位置上的数据被覆盖
但是我们以及提前将i位置上的数据保存在temp中了
接下来要从i位置上开始和temp进行循环比较,如果是s[i]<=temp且i<j,则进行i++操作
如果s[i]数据大于temp则循环结束,将i位置上的数据赋值到j位置上去
j位置上的数据在查找s[j]>temp时就已经将j位置上的数据赋值到i上去了
当i与j重合的时就是temp所该存在的位置
s[i]=temp或者s[j]=temp
3.分组重复前两步
通过递归进行左部分排序
通过递归进行右部分排序
二、代码实现
#include <stdio.h>
void quick(int *s, int i, int j); //声明快排函数
int main(int argc, const char *argv[])
{
int s[7] = {8, 4, 13, 67, 99, 23, 15};
int i = 0;
for (; i < 7; i++) //排序前进行遍历
{
printf("%d ", s[i]);
}
puts("");
quick(s, 0, 6);
for (i = 0; i < 7; i++) //排序后进行遍历
{
printf("%d ", s[i]);
}
puts("");
return 0;
}
void quick(int *s, int i, int j)
{
if (i < j) //递归入口
{
int temp = s[i]; //挑元素
int begin = i;
int end = j;
while (i < j)
{ //划分组
while (i < j && temp < s[j])
{
j--;
}
s[i] = s[j]; //小于temp的值进行左移
while (i < j && temp >= s[i])
{
i++;
}
s[j] = s[i]; //大于等于temp的值进行右移
}
s[i] = temp; //确定temp应在的位置
quick(s, begin, i - 1); //左组重复前两部
quick(s, j + 1, end); //右组重复前两部
}
else //递归出口
{
return ;
}
}
三、结果展示
成功实现