交换排序:利用交换数据元素位置的方法进行排序的方法
一、冒泡排序
基本思想:将序列中第一个记录与第二个记录比较,若前一个大于后一个,则交换位置。然后比较第二个和第三个,第三个和第四个,以此类推,一轮之后,序列中最大的元素就到了序列最后的位置上。继续进行第2轮,第3轮,第n-1轮。若其中某一轮途中没有元素交换,则证明序列已经排好序,后面的轮次不需要再进行。冒泡排序是稳定的排序。
排序过程如图所示:
C++代码:
#include<iostream>
using namespace std;
int * bubbleSort(int *a, int length) {
int i, j, change;
//记录当前轮次中有没有元素交换
change = 1;
j = length - 1;
while (j > 0 && change) {
change = 0;
for (i = 0; i < j; i++) {
if (a[i] > a[i + 1]) {
//交换
int temp = a[i];
a[i] = a[i+1];
a[i + 1] = temp;
change = 1;
}
}
}
return a;
}
int main() {
int length = 10;
int a[10] = { 65,34,25,12,56,14,92,23,87,46 };
int number = 3;
int d[3] = {5,3,1};
cout << "排序前:";
for (int i = 0; i < length; i++) {
cout << a[i] << " ";
}
cout << endl;
int *p = bubbleSort(a,length);
cout <<endl<< "排序后:";
for (int i = 0; i < length; i++) {
cout << p[i] << " ";
}
system("pause");
return 0;
}
空间复杂度:Ο(1)
时间复杂度:Ο(n^2)
二、快速排序
快速排序又叫分区交换排序,它是对冒泡排序的一种改进,是目前已知排序方法中最快的一种。
基本思想:从待排序的序列中选取一个元素R(一般选取第一个)作为标准,调整所有记录的位置,使得R之前的记录均小于R,R之后的记录均大于R,即一个快速排序之后,R被放到了最终的位置上。同时,R把原序列划分为两个子序列,对两个子序列继续使用该方法,直到所有子序列的长度为1时排序完成。快速排序是一个递归的过程。快速排序是不稳定的排序。
排序过程图示:
C++代码:
#include<iostream>
using namespace std;
//快速排序
//分割(单次快排,寻找标准元素的位置)
int Partition(int a[], int low, int high) {
int temp = a[low];//当前需要寻找位置的数据元素
while (low < high) {
while (low < high && a[high]>=temp) {
high--;
}
//将小于标准元素的数据往前放
if (a[high] < temp) {
a[low] = a[high];
low++;
}
while (low < high && a[low]<=temp) {
low++;
}
//将大于标准元素的数据往后放
if (a[low] > temp) {
a[high] = a[low];
high--;
}
}
a[low] = temp; //标准元素移动到正确的位置
return low; //返回标准位置
}
//快速排序
//排序
void QSort(int a[], int low, int high){
int standardLocation;
if (low < high) {
standardLocation = Partition(a, low, high);
cout << "standardLocation=" << standardLocation << ",low=" << low << ",high=" << high << endl;
cout << "排序中间结果:";
for (int i = 0; i < 10; i++) {
cout << a[i] << " ";
}
cout << endl;
QSort(a, low, standardLocation-1);
QSort(a, standardLocation+1, high);
}
}
int * QuickSort(int a[], int length) {
QSort(a, 0, length-1);
return a;
}
int main() {
int length = 10;
int a[10] = { 65,34,25,12,56,14,92,23,87,46 };
int number = 3;
int d[3] = {5,3,1};
cout << "排序前:";
for (int i = 0; i < length; i++) {
cout << a[i] << " ";
}
cout << endl;
int *p = QuickSort(a, length);
cout << endl << "排序后:";
for (int i = 0; i < length; i++) {
cout << p[i] << " ";
}
system("pause");
return 0;
}
空间复杂度:Ο(n)
时间复杂度:Ο(nlog_2n)
快速排序复杂度分析:
时间复杂度:快速排序的时间复杂度取决于标准记录的选择。
a.最快的情况
如果每次选的标准记录都是中间数,则序列总是被分为长度基本相等的子序列。若完成n个记录排序所需时间为T(n),则有:
其中k表示分解的次数,这种情况下分解过程可以描述为一颗满二叉树,分解的次数为树的深度log_2n。所以有:
b.最坏的情况
如果每次选择的记录都是当前序列的最小数,则总是把序列分为一个空子序列和一个长度为原长度减一的子序列,这时,总比较次数为:
若原始记录时已经排好序(与要求的顺序相反)的序列,且每次选取的是第一个作为标准元素,快速排序则变成了时间复杂度为Ο(n^2)的慢排序。但是一般情况下,待排序的是随机的,所以快速排序的平均比较次数为Ο(nlog_2n),由于快速排序元素的移动次数和比较次数相比少很多,故快速排序的时间复杂度为Ο(nlog_2n)
空间复杂度:递归式快速排序需要环境栈存储分割点,栈的深度最好情况下为log_2n,最坏情况下为n,因此快速排序的空间复杂度为O(n)。
快速排序不稳定性举例
例如(5,3A,6,3B)对这个进行排序,排序之前相同的数3A与3B,A在B的前面,经过排序之后会变成
(3B,3A,5,6),所以说快速排序是一个不稳定的排序
三、快速排序的非递归形式
用堆栈存储中间数据,代替递归。栈结构可以用数组模拟
#include<iostream>
using namespace std;
//快速排序
//分割(单次快排,寻找标准元素的位置)
int Partition(int a[], int low, int high) {
int temp = a[low];//当前需要寻找位置的数据元素
while (low < high) {
while (low < high && a[high]>=temp) {
high--;
}
//将小于标准元素的数据往前放
if (a[high] < temp) {
a[low] = a[high];
low++;
}
while (low < high && a[low]<=temp) {
low++;
}
//将大于标准元素的数据往后放
if (a[low] > temp) {
a[high] = a[low];
high--;
}
}
a[low] = temp; //标准元素移动到正确的位置
return low; //返回标准位置
}
//快速排序—非递归形式
int * QuickSort_NonRecursive(int a[], int length) {
//用数组模拟栈结构
int *stack = new int[length];
int top = 0;
int low = 0;
int high = length - 1;
int par = Partition(a, low, high);
// 入栈
if(par > low+1){
stack[top++] = low;
stack[top++] = par-1;
}
if(par < high-1){
stack[top++] = par+1;
stack[top++] = high;
}
//出栈
while(top > 0){
high = stack[--top];
low = stack[--top];
par = Partition(a, low, high);
//再入栈
if(par > low+1){
stack[top++] = low;
stack[top++] = par-1;
}
if(par < high-1){
stack[top++] = par+1;
stack[top++] = high;
}
}
return a;
}
int main() {
int length = 10;
int a[10] = { 65,34,25,12,56,14,92,23,87,46 };
int number = 3;
int d[3] = {5,3,1};
cout << "排序前:";
for (int i = 0; i < length; i++) {
cout << a[i] << " ";
}
cout << endl;
int *p = QuickSort_NonRecursive(a, length);
cout << endl << "排序后:";
for (int i = 0; i < length; i++) {
cout << p[i] << " ";
}
system("pause");
return 0;
}
相关文章
https://mp.csdn.net/postedit/87636287 十大排序算法对比与总结
参考博客:https://blog.csdn.net/qq_39475906/article/details/80338568