数据结构C++——交换排序(冒泡排序和快速排序)
一、待排序的数据类型定义
待排序的数据类型
/*------------待排序记录的数据结构类型定义----------*/
#define MAXSIZE 1001//顺序表的最大长度
typedef int KeyType;//定义关键字类型为整型
typedef int InfoType;
typedef struct {
KeyType key;//关键字项
InfoType otherinfo;//其他数据项
}RedType;//记录类型
typedef struct {
RedType r[MAXSIZE + 1];//r[0]闲置或用做哨兵单元
int length;//顺序表长度
}SqList;//顺序表类型
二、冒泡排序
冒泡排序
冒泡排序是一种最简单的交换排序方法,它通过两两比较相邻记录的关键字,如果发生逆序,则进行交换,从而使关键字小的记录如气泡一般逐渐往上 "漂浮"(左移),或者使关键字大的记录如石块一样逐渐向下 "坠落”(右移)。
冒泡排序算法思路:
1:n个数据排序则一共排序n-1躺
2:设置变量标志flag用来标记某一趟排序是否发生交换
3:每一趟排序都将数值最大的数放在末尾,每进行一次排序则排序次数m减1
4:直至数据变得有序或排序次数=0,跳出循环,排序结束
/*-----------冒泡排序-------------*/
void BubbleSort(SqList& L) {
//对顺序表L做冒泡排序
int m = L.length - 1; int flag = 1;//flag用来标记某一趟排序是否发生交换
while ((m > 0) && flag == 1) {
flag = 0;//flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序
for(int j=1;j<m;j++)
if (L.r[j].key > L.r[j + 1].key) {
flag = 1;//flag置为1,表示本趟排序发生了交换
RedType t = L.r[j];
L.r[j] = L.r[j + 1];
L.r[j + 1] = t;//交换前后两个记录
}
m--;
}
}
三、快速排序
快速排序
快速排序是由冒泡排序改进而得的。 在 冒泡排序过程中, 只对相邻的两个记录进行比较, 因此每次交换两个相邻记录时只能消除一个逆序。 如果能通过两个(不相邻)记录的一次交换,消除多个逆序, 则会大大加快排序的速度。 快速排序方法中的一次交换可能消除多个逆序。
快速排序的算法思路:
1:将一号单元值设为哨兵值,作为枢轴值
2:从表的两端交替向中间扫描,将比枢轴值小的值放在枢轴左边,比枢轴大的值放在枢轴右边
3:当low和high相等后,将哨兵值赋值给low号单元值,即将枢轴值记录到位
4:递归排序枢轴的左子表和右子表,递归结束则排序结束
/*-----------快速排序--------------*/
int Partition(SqList& L, int low, int high) {
//对顺序表L中的子表r[low...high]进行一躺排序,返回枢轴位置
L.r[0] = L.r[low];//用子表的第一个记录做枢轴记录
int pivotkey = L.r[low].key;//枢轴记录关键字保存在pivotkey中
while (low < high) {
//从表的两端交替地向中间扫描
while (low < high && L.r[high].key >= pivotkey) --high;
L.r[low] = L.r[high];//将比枢轴记录小的记录移到低端
while (low < high && L.r[low].key <= pivotkey) ++low;
L.r[high] = L.r[low];//将比枢轴记录大的记录移到高端
}
L.r[low] = L.r[0];//枢轴记录到位
return low;//返回枢轴位置
}
void QSort(SqList& L, int low, int high) {
//调用前置赋值:low=1;high=L.length;
//对顺序表L中的子序列L.r[low..high]做快速排序
if (low < high) {//长度大于1
int pivotloc = Partition(L, low, high);//将L.r[low...high]一分为二,pivotloc是枢轴位置
QSort(L, low, pivotloc - 1);//对左子表递归排序
QSort(L, pivotloc + 1, high);//对右子表递归排序
}
}
void QuickSort(SqList& L) {
//对顺序表做快速排序
QSort(L, 1, L.length);
}
四、测试的完整代码
完整代码
#include<iostream>
using namespace std;
/*------------待排序记录的数据结构类型定义----------*/
#define MAXSIZE 1001//顺序表的最大长度
typedef int KeyType;//定义关键字类型为整型
typedef int InfoType;
typedef struct {
KeyType key;//关键字项
InfoType otherinfo;//其他数据项
}RedType;//记录类型
typedef struct {
RedType r[MAXSIZE + 1];//r[0]闲置或用做哨兵单元
int length;//顺序表长度
}SqList;//顺序表类型
/*----------创建顺序表---------*/
void CreateList(SqList& L) {
//cout << "请输入待排序数的个数:" << endl;
int n = 0;
cin >> n;
for (int i = 1; i < n+1; i++)
cin >> L.r[i].key;
L.length = n;
}
/*-----------冒泡排序-------------*/
void BubbleSort(SqList& L) {
//对顺序表L做冒泡排序
int m = L.length - 1; int flag = 1;//flag用来标记某一趟排序是否发生交换
while ((m > 0) && flag == 1) {
flag = 0;//flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序
for(int j=1;j<m;j++)
if (L.r[j].key > L.r[j + 1].key) {
flag = 1;//flag置为1,表示本趟排序发生了交换
RedType t = L.r[j];
L.r[j] = L.r[j + 1];
L.r[j + 1] = t;//交换前后两个记录
}
m--;
}
}
/*-----------快速排序--------------*/
int Partition(SqList& L, int low, int high) {
//对顺序表L中的子表r[low...high]进行一躺排序,返回枢轴位置
L.r[0] = L.r[low];//用子表的第一个记录做枢轴记录
int pivotkey = L.r[low].key;//枢轴记录关键字保存在pivotkey中
while (low < high) {
//从表的两端交替地向中间扫描
while (low < high && L.r[high].key >= pivotkey) --high;
L.r[low] = L.r[high];//将比枢轴记录小的记录移到低端
while (low < high && L.r[low].key <= pivotkey) ++low;
L.r[high] = L.r[low];//将比枢轴记录大的记录移到高端
}
L.r[low] = L.r[0];//枢轴记录到位
return low;//返回枢轴位置
}
void QSort(SqList& L, int low, int high) {
//调用前置赋值:low=1;high=L.length;
//对顺序表L中的子序列L.r[low..high]做快速排序
if (low < high) {//长度大于1
int pivotloc = Partition(L, low, high);//将L.r[low...high]一分为二,pivotloc是枢轴位置
QSort(L, low, pivotloc - 1);//对左子表递归排序
QSort(L, pivotloc + 1, high);//对右子表递归排序
}
}
void QuickSort(SqList& L) {
//对顺序表做快速排序
QSort(L, 1, L.length);
}
/*-----------输出排序结果----------*/
void PrintResut(SqList& L) {
for (int i = 1; i < L.length+1; i++)
cout << L.r[i].key << " ";
}
int main() {
SqList L;
CreateList(L);
//BubbleSort(L);
QuickSort(L);
PrintResut(L);
return 0;
}
输入:
10
2 8 4 6 1 10 7 3 5 9
输出:
1 2 3 4 5 6 7 8 9
五、总结
以上为笔者对于交换排序的一些见解,希望初学者都能有所收获,有技术不到位的地方,还望各位大佬指正。
同时,笔者的个人主页还有数据结构其他部分的一些见解与分析,后续数据结构的相关知识还将陆续更新,欢迎大家访问且共同学习!