您的位置:首页 > 理论基础 > 数据结构算法

数据结构编程笔记二十七:第十章 内排序 各种排序算法的实现

2017-09-17 22:32 260 查看
上次我们介绍了二叉排序树的实现,这次介绍各种排序算法的实现。

还是老规矩:

程序在码云上可以下载。

地址:https://git.oschina.net/601345138/DataStructureCLanguage.git

排序算法的解释就省略了,书上都有。

内排序算法用到了顺序表,其基本操作可以参考《数据结构编程笔记三:第二章 线性表 顺序表的实现》一文,在此不再赘述。

直接看代码吧:

//*************************引入头文件****************************
#include <stdio.h>
#include <stdlib.h>

//************************自定义符号常量*************************

#define OVERFLOW -2         //内存溢出错误常量
#define ILLEGAL -1          //非法操作错误常量
#define OK 1                //表示操作正确的常量
#define ERROR 0             //表示操作错误的常量
#define TRUE 1              //表示逻辑正确的常量
#define FALSE 0             //表示逻辑错误的常量
#define MAXSIZE 20          //一个用作示例的小顺序表的最大长度
#define EQ(a,b) ((a)==(b))  //相等
#define LT(a,b) ((a)< (b))  //小与
#define LQ(a,b) ((a)<= (b)) //小与等于

//**********************自定义数据类型************************

typedef int Status;   //状态标志
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.初始化顺序表----------------------

/*
函数:InitList_Sq
参数:SqList &L 顺序表引用
返回值:状态码,操作成功返回OK
作用:根据用户输入创建一棵二叉排序树
*/
Status InitList_Sq(SqList &L){

printf("您想给顺序表初始化多少个元素?(输入一个不超过20的整数)  ");
scanf("%d", &L.length);

printf("请输入顺序表的所有元素(用空格隔开)\n");
for(int i = 1; i <= L.length; ++i) {
scanf("%d", &L.r[i].key);

//记录元素的初始位置
L.r[i].otherinfo = i;
}//for

//操作成功
return OK;
}//InitList_Sq

/*
函数:CopyList
参数:SqList L1 复制源
SqList &L2 目的地
返回值:状态码,操作成功返回OK
作用:表的复制和恢复(便于后续演示)
*/
Status CopyList(SqList L1, SqList &L2){

//将L1复制到L2
L2.length = L1.length;

for(int i = 0; i <= L1.length; ++i) {
L2.r[i] = L1.r[i];
}//for

//操作成功
return OK;
}//CopyList

//-----------------------2.遍历顺序表-----------------------

/*
函数:Print
参数:RedType r 被访问记录
返回值:状态码,操作成功返回OK
作用:元素访问函数
*/
Status Print(RedType r) {

//以控制台输出的方式访问记录
printf("%d[%d] ", r.key, r.otherinfo);

//操作成功
return OK;
}//Print

/*
函数:ListTraverse_Sq
参数:SqList L 顺序表L
Status(* Visit)(RedType) 元素访问函数
返回值:状态码,操作成功返回OK
作用:顺序表遍历
*/
Status ListTraverse_Sq(SqList L, Status(* Visit)(RedType)) {

//循环遍历顺序表中所有记录
for(int i = 1; i <= L.length; ++i) {

//访问每个元素一次且仅一次,一旦访问失败则遍历失败
//if(!Visit(L.r[i])) <=> if(Visit(L.r[i]) == ERROR)
if(!Visit(L.r[i])) {

//遍历失败
return ERROR;
}//if
}//for

//输出空格,使结果美观
printf("\n");

//操作成功
return OK;
}//ListTraverse_Sq

//------------------------3.排序算法-----------------------

//-------------------直接插入排序-----------------------

/*
函数:InsertSort
参数:SqList &L 顺序表引用
返回值:无
作用:直接插入排序
*/
void InsertSort(SqList &L){

int j;

for(int i = 2; i <= L.length; ++i) {

//"<",需将L.r[i]插入有序子集
if(LT(L.r[i].key, L.r[i-1].key)){

//复制为“哨兵”
L.r[0] = L.r[i];

//记录后移,腾出插入位置
L.r[i] = L.r[i-1];
for(j = i-2; LT(L.r[0].key, L.r[j].key); --j) {
L.r[j + 1] = L.r[j];
}//for

//插入到正确位置
L.r[j + 1] = L.r[0];
}//if
}//for
}//InsertSort

//------------------折半插入排序--------------------

/*
函数:BInsertSort
参数:SqList &L 顺序表引用
返回值:无
作用:对顺序表L作折半插入排序
*/
void BInsertSort(SqList &L) {

//high、low和m是三个指针。m就是mid
int high, low, m;

for(int i = 2; i <= L.length; ++i) {

//L.r[0]是哨兵
L.r[0] = L.r[i];

//low的初始值是1,low指向第一条记录
low = 1;

//high的初始值为i-1,high指向最后一条记录
high = i - 1;

//在r[low..high]中折半查找有序插入的位置
while(low <= high){

//折半
m = (low + high) / 2;

//待查找关键字的值小于mid指向的记录,说明插入点在低半区
if(LT(L.r[0].key, L.r[m].key)) {

//修改high指针到低半区去找
high = m - 1;
}//if
//待查找关键字的值大于mid指向的记录,说明插入点在高半区
else {

//修改low指针在高半区找
low = m + 1;
}//else
}//while

//记录后移,腾出插入位置
for(int j = i - 1; j >= high + 1; --j) {
L.r[j + 1] = L.r[j];
}//for

//插入记录
L.r[high + 1] = L.r[0];
}//for
}//BinsertSort

//-------------------希尔排序--------------------------

/*
函数:BInsertSort
参数:SqList &L 顺序表引用
int dk 增量,控制跳跃程度
返回值:无
作用:对顺序表L作一趟希尔插入排序,本算法是和一趟直接插入排序相比,
做了以下修改:
1.前后记录位置的增量是dk,而不是1
2.r[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已找到
*/
void ShellInsert(SqList &L, int dk){

int j;

//需将L.r[i]插入有序增量子表
for(int i = dk + 1; i <= L.length; ++i) {

if(LT(L.r[i].key, L.r[i-dk].key)){

//暂存在L.r[0]
L.r[0] = L.r[i];

//记录后移,查找插入位置
for(j = i - dk; j > 0 && LT(L.r[0].key, L.r[j].key); j -= dk) {
L.r[j + dk] = L.r[j];
}//for

//插入
L.r[j + dk] = L.r[0];
}//if
}//for
}//ShellInsert

/*
函数:ShellSort
参数:SqList &L 顺序表引用
int dlta[] 增量数组
int t 增量数组中的元素个数(数组长度)
返回值:无
作用:按增量序列dlta[0..t-1]对顺序表L作希尔排序
*/
void ShellSort(SqList &L, int dlta[], int t){

for(int k = 0; k < t; ++k) {

//一趟增量为dlta[k]的插入排序
ShellInsert(L, dlta[k]);
}//for
}//ShellSort

//-----------------起泡排序(改进) ------------------------------

/*
函数:bubble_sort
参数:SqList &L 顺序表引用
返回值:无
作用:将a中整数序列排列成自小至大有序的序列(起泡排序)
*/
void bubble_sort(SqList &L){

//辅助单元:用于保存交换值的临时变量
RedType temp;

//冒泡排序主循环
for(int i = 1, change = TRUE; (i <= L.length - 1) && change; ++i){

//每趟冒泡开始前要初始化change的值为false
//直到确实有交换必要时才更改此值
change = FALSE;

for(int j = 1; j <= L.length - i; ++j) {

//发现相邻两位置元素大小顺序不是我们想要的顺序
//LT(L.r[j+1].key, L.r[j].key)相当于L.r[j+1].key > L.r[j].key
//所以这样冒泡出来的结果是升序排列。
//若想改为降序,只需要修改这里的比较条件就可以了
if(LT(L.r[j + 1].key, L.r[j].key)){

//交换L.r[j]和L.r[j+1]
temp = L.r[j];
L.r[j] = L.r[j + 1];
L.r[j + 1] = temp;

//由于这一趟发生了交换,记录可能只是移动了一个位置,
//但还没有到达最终位置,则有可能还要继续交换(冒泡),
//所以change要设置为true
change = TRUE;
}//if
}//for
}//for
}//bubble_sort

//-----------------快速排序---------------------------------------

/*  Partition意为“分割 ”
函数:Partition
参数:SqList &L 顺序表引用
int low 低位指针,保存记录的下标
int high 高位指针,保存记录的下标
返回值:无
作用:交换顺序表L中子表r[low..high]的记录,枢轴记录到位,
并返回其所在位置。此时在它之前(后)的记录均不大(小)于它。
*/
int Partition(SqList &L, int low, int high) {

//用子表的第一个记录作枢轴记录
L.r[0] = L.r[low];
printf("->本趟排序枢轴记录是:%d\n", L.r[0]);

//枢轴记录关键字
KeyType pivotkey = L.r[low].key;

//从表的两端交替地向中间扫描,当low = high时,退出循环
while(low < high){

//高位指针high从后向前移动,直到遇到比枢轴记录
//关键字小的记录,此时high指向这条记录
while(low < high && L.r[high].key >= pivotkey) {
--high;
}//while

//将比枢轴记录小的记录移到低端
L.r[low] = L.r[high];

//将high位置的记录的关键字修改为-1,-1表示空位置
L.r[high].key = -1;
printf("high移动到%d,交换low = %d处的记录为%d:(-1表示该位置为空)\n",
high, low, L.r[low]);

//遍历顺序表,查看交换后的顺序表记录位置的变化
ListTraverse_Sq(L, Print);

//低位指针low从前向后移动,直到遇到比枢轴记录
//关键字大的记录,此时high指向这条记录
while(low < high && L.r[low].key <= pivotkey) {
++low;
}//while

//将比枢轴记录大的记录移到高端
L.r[high] = L.r[low];

//将low位置的记录的关键字修改为-1,-1表示空位置
L.r[low].key = -1;

if(low != high) {
printf("low 移动到%d,交换high = %d处的记录为%d:(-1表示该位置为空)\n"
, low, high, L.r[high]);

//查看顺序表在元素交换后的变化
ListTraverse_Sq(L,Print);
}//if
}//while

//枢轴记录到位
L.r[low] = L.r[0];

//输出排序后的结果
printf("->本趟排序完成后:\n");
ListTraverse_Sq(L, Print);

//输出换行使结果美观
printf("\n");

//返回枢轴位置
return low;
}//Partition

/*
函数:QSort
参数:SqList &L 顺序表引用
int low 低位指针,保存记录的下标
int high 高位指针,保存记录的下标
返回值:无
作用:对顺序表L中的子序列L.r[low..high]作快速排序
*/
void QSort(SqList &L, int low, int high){

//pivotloc记录了枢轴元素所在位置
int pivotloc;

//长度大于1
if(low < high){

//将L.r[low..high]一分为二
pivotloc = Partition(L, low, high);

//对低子表递归排序,pivotloc是枢轴位置
QSort(L, low, pivotloc - 1);

//对高子表递归排序
QSort(L, pivotloc + 1, high);
}//if
}//QSort

/*
函数:QuickSort
参数:SqList &L 顺序表引用
返回值:无
作用:对顺序表L作快速排序
*/
void QuickSort(SqList &L){

//对所有记录调用快速排序算法
QSort(L, 1, L.length);
}//QuickSort

//-----------------选择排序------------------

/*
函数:SelectMinKey
参数:SqList &L 顺序表引用
int i 选择的起始位置
返回值:返回在L.r[i..L.length]中key最小的记录的序号
作用:得到在L.r[i..L.length]中key最小的记录的序号
*/
int SelectMinKey(SqList L, int i){

//临时变量,用于保存找到的最小值
KeyType min;

//开始假设第i条记录的关键字为最小值
int k = i;

//最小值为第i条记录的关键字的值
min = L.r[i].key;

//从第i+1条记录开始到最后一条记录结束扫描
//尝试找出比min更小的关键字
for(int j = i + 1; j <= L.length; j++) {

//找到更小的关键字
if(L.r[j].key<min){

//k记录了新的最小值的下标
k = j;

//min记录了新的最小值
min = L.r[j].key;
}//if
}//for

//扫描完成后,k记录了最小值所在下标,返回k即可
return k;
}//SelectMinKey

/*
函数:SelectSort
参数:SqList &L 顺序表引用
返回值:无
作用:对顺序表L作简单选择排序
*/
void SelectSort(SqList &L){

//辅助空间:临时变量,交换用
RedType temp;

//j记录了在L.r[i..L.length]中选出的key最小的记录所在位置
int j;

//选择第i小的记录,并交换到位
for(int i = 1; i < L.length; ++i) {

//在L.r[i..L.length]中选择key最小的记录
j = SelectMinKey(L, i);

//若最小值不在当前位置,则需要作交换操作
//把最小值换过来
if(i != j){

//交换操作
temp = L.r[i];

//注意:结构体直接赋值相当于结构体各个分量都赋一次值
L.r[i] = L.r[j];
L.r[j] = temp;
}//if
}//for
}//SelectSort

//-----------------归并排序----------------------

/*
函数:Merge
参数:RedType SR[] 被归并数组
RedType TR[] 存放归并结果的数组
int i 记录下标,第一段归并序列的起始位置
int m 记录下标,第一段归并序列的结束位置
int n 记录下标,第二段归并序列的结束位置
返回值:无
作用:将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]
说明:RedType TR[]不应写成RedType &TR[],因为引用型形参实际上
是取实参的地址,从而获得修改实参的能力。而这里给函数
传递的是实参数组的首地址,地址是无法再取地址的。
实际上,把实参数组的首地址传给函数后,函数已经获得
修改实参数组元素的能力。
*/
void Merge(RedType SR[], RedType TR[], int i, int m, int n){

//临时变量
int j, k;

//将SR中的记录由小到大地并入TR
for(j = m + 1, k = i; i <= m && j <= n; ++k){

//SR[i].key <= SR[j].key
if(LQ(SR[i].key, SR[j].key)) {
TR[k] = SR[i++];
}//if
else {
TR[k] = SR[j++];
}//else
}//for

//SR[i..m]还有剩余元素没有归并到TR数组中
if(i <= m){

//将剩余的SR[i..m]复制到TR
for(int l = 0; l <= m - i; l++) {
TR[k + l] = SR[i + l];
}//for
}//if

//SR[j..n]还有剩余元素没有归并到TR数组中
if(j <= n){

//将剩余的SR[j..n]复制到TR
for(int l = 0; l <= n - j; l++) {
TR[k + l] = SR[j + l];
}//for
}//if
}//Merge

/*
函数:MSort
参数:RedType SR[] 被归并数组
RedType TR[] 存放归并结果的数组
int s 归并开始位置
int t 归并结束为止
返回值:无
作用:将SR[s..t]归并排序为TR1[s..t]
*/
void MSort(RedType SR[], RedType TR1[], int s, int t){

RedType TR2[MAXSIZE + 1];

//只有一个元素
if(s == t) {
TR1[s] = SR[s];
}//if
else{

//将SR[s..t]平分为SR[s..m]和SR[m+1..t]
//m记录了中间位置
int m = (s + t) / 2;

//递归地将SR[s..m]归并为有序的TR2[s..m]
MSort(SR, TR2, s, m);

//递归地将SR[m+1..t]归并为有序的TR2[m+1..t]
MSort(SR, TR2, m + 1, t);

//将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t]
Merge(TR2, TR1, s, m, t);
}//else
}//MSort

/*
函数:MergeSort
参数:SqList &L 顺序表
返回值:无
作用:对顺序表L作归并排序
*/
void MergeSort(SqList &L){

//对所有记录进行归并
MSort(L.r, L.r, 1, L.length);
}//MergeSort

//--------------------------堆排序-------------------------
typedef SqList HeapType; // 堆采用顺序表存储表示

/*
函数:MergeSort
参数:HeapType &H 堆的引用(其实就是个顺序表)
int s 堆在顺序表中的开始位置
int m 堆在顺序表中的结束位置
返回值:无
作用:已知H.r[s..m]中记录的关键字除H.r[s].key之外均满足堆的定义,
调整H.r[s]的关键字,使H.r[s..m]成为一个大顶堆
(对其中记录的关键字而言)
*/
void HeapAdjust(HeapType &H, int s, int m) {

//临时变量
RedType rc = H.r[s];

//沿key较大的孩子结点向下筛选
for(int j = 2 * s; j <= m; j *= 2) {

if(j < m && LT(H.r[j].key, H.r[j+1].key)) {

//j为key较大的记录的下标
++j;
}//if

//rc应插入在位置s上
if(!LT(rc.key, H.r[j].key)) {
break;
}//if

H.r[s] = H.r[j];
s = j;
}//for

//插入
H.r[s] = rc;
}//HeapAdjust

/*
函数:MergeSort
参数:HeapType &H 堆的引用(其实就是个顺序表)
返回值:无
作用:对顺序表H进行堆排序。
*/
void HeapSort(HeapType &H) {

//临时变量t,用于交换
RedType t;

//把H.r[1..H.length]建成大顶堆
for(int i = H.length / 2; i > 0; --i) {
HeapAdjust(H, i, H.length);
}//for

//将H.r[1..i-1]重新调整为大顶堆
for(int i = H.length; i > 1; --i) {

//将堆顶记录和当前未经排序子序列H.r[1..i]中最后一个记录相互交换
t = H.r[1];
H.r[1] = H.r[i];
H.r[i] = t;

//将H.r[1..i-1]重新调整为大顶堆
HeapAdjust(H,1,i-1);
}//for
}//HeapSort

//************************主函数****************************
int main(int argc,char *argv[]){

SqList L1, L2;
int flag;
char MainMenu[]=  "*********************************内排序算法测试*********************************\n"
"\t\t\t\t1.初始化顺序表\n"
"\t\t\t\t2.遍历顺序表\n"
"\t\t\t\t3.直接插入排序\n"
"\t\t\t\t4.折半插入排序\n"
"\t\t\t\t5.希尔排序\n"
"\t\t\t\t6.起泡(改进)排序\n"
"\t\t\t\t7.快速排序\n"
"\t\t\t\t8.选择排序\n"
"\t\t\t\t9.归并排序\n"
"\t\t\t\t10.堆排序\n"
"\t\t\t\t11.还原顺序表的原始顺序\n"
"\t\t\t\t12.退出程序\n"
"请选择您需要的功能:";
while(1){
printf(MainMenu);  //打印菜单
switch(scanf("%d", &flag), flag){

//初始化
case 1:{
InitList_Sq(L1);  //初始化顺序表
CopyList(L1, L2);  //保存一个L1的备份,用于后续演示
break;
}//case

//遍历测试块
case 2:{
printf("遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//直接插入排序测试块
case 3:{
printf("排序前对顺序表进行遍历([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
InsertSort(L1);
printf("直接插入排序后遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//折半插入排序测试块
case 4:{
printf("\n排序前对顺序表进行遍历([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
BInsertSort(L1);
printf("折半插入排序后遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//希尔排序测试块
case 5:{

//增量序列
int dlta[3] = {5, 3, 1};
printf("\n排序前对顺序表进行遍历([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
ShellSort(L1, dlta, 3);
printf("希尔排序后遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//起泡排序(改进)测试块
case 6:{
printf("\n排序前对顺序表进行遍历([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
bubble_sort(L1);
printf("起泡排序后遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//快速排序测试块
case 7:{
printf("\n排序前对顺序表进行遍历([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
QuickSort(L1);
printf("快速排序后遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//选择排序测试块
case 8:{
printf("\n排序前对顺序表进行遍历([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
SelectSort(L1);
printf("选择排序后遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//归并排序测试块
case 9:{
printf("\n排序前对顺序表进行遍历([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
MergeSort(L1);
printf("归并排序后遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//堆排序测试块
case 10:{
printf("\n排序前对顺序表进行遍历([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
HeapSort(L1);
printf("堆排序后遍历顺序表([]内数字为其所在位置):\n");
ListTraverse_Sq(L1, Print);
break;
}//case

//恢复L1内容
case 11:{
CopyList(L2, L1);
break;
}//case

//退出
case 12:{
exit(0);
break;
}//case

//非法
default:{
printf("输入非法!\n");
}//default
}//switch
system("PAUSE");
system("cls");
}//while
return 0;
}//main


运行输入的数据和程序输出的结果:

*********************************内排序算法测试*********************************
1.初始化顺序表
2.遍历顺序表
3.直接插入排序
4.折半插入排序
5.希尔排序
6.起泡(改进)排序
7.快速排序
8.选择排序
9.归并排序
10.堆排序
11.还原顺序表的原始顺序
12.退出程序
请选择您需要的功能:1
您想给顺序表初始化多少个元素?(输入一个不超过20的整数)  10
请输入顺序表的所有元素(用空格隔开)
2 45 8 6 3 12 7 56 4 29
请按任意键继续. . .

请选择您需要的功能:2
遍历顺序表([]内数字为其所在位置):
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
请按任意键继续. . .

请选择您需要的功能:3
排序前对顺序表进行遍历([]内数字为其所在位置):
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
直接插入排序后遍历顺序表([]内数字为其所在位置):
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]
请按任意键继续. . .

请选择您需要的功能:11
请按任意键继续. . .

请选择您需要的功能:4
排序前对顺序表进行遍历([]内数字为其所在位置):
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
折半插入排序后遍历顺序表([]内数字为其所在位置):
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]
请按任意键继续. . .

请选择您需要的功能:11
请按任意键继续. . .

请选择您需要的功能:5
排序前对顺序表进行遍历([]内数字为其所在位置):
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
希尔排序后遍历顺序表([]内数字为其所在位置):
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]
请按任意键继续. . .

请选择您需要的功能:11
请按任意键继续. . .

请选择您需要的功能:6
排序前对顺序表进行遍历([]内数字为其所在位置):
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
起泡排序后遍历顺序表([]内数字为其所在位置):
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]
请按任意键继续. . .

请选择您需要的功能:11
请按任意键继续. . .

请选择您需要的功能:7

排序前对顺序表进行遍历([]内数字为其所在位置):
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
->本趟排序枢轴记录是:2
high移动到1,交换low = 1处的记录为-1:(-1表示该位置为空)
-1[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
->本趟排序完成后:
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]

->本趟排序枢轴记录是:45
high移动到10,交换low = 2处的记录为29:(-1表示该位置为空)
2[1] 29[10] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] -1[10]
low 移动到8,交换high = 10处的记录为56:(-1表示该位置为空)
2[1] 29[10] 8[3] 6[4] 3[5] 12[6] 7[7] -1[8] 4[9] 56[8]
high移动到9,交换low = 8处的记录为4:(-1表示该位置为空)
2[1] 29[10] 8[3] 6[4] 3[5] 12[6] 7[7] 4[9] -1[9] 56[8]
->本趟排序完成后:
2[1] 29[10] 8[3] 6[4] 3[5] 12[6] 7[7] 4[9] 45[2] 56[8]

->本趟排序枢轴记录是:29
high移动到8,交换low = 2处的记录为4:(-1表示该位置为空)
2[1] 4[9] 8[3] 6[4] 3[5] 12[6] 7[7] -1[9] 45[2] 56[8]
->本趟排序完成后:
2[1] 4[9] 8[3] 6[4] 3[5] 12[6] 7[7] 29[10] 45[2] 56[8]

->本趟排序枢轴记录是:4
high移动到5,交换low = 2处的记录为3:(-1表示该位置为空)
2[1] 3[5] 8[3] 6[4] -1[5] 12[6] 7[7] 29[10] 45[2] 56[8]
low 移动到3,交换high = 5处的记录为8:(-1表示该位置为空)
2[1] 3[5] -1[3] 6[4] 8[3] 12[6] 7[7] 29[10] 45[2] 56[8]
high移动到3,交换low = 3处的记录为-1:(-1表示该位置为空)
2[1] 3[5] -1[3] 6[4] 8[3] 12[6] 7[7] 29[10] 45[2] 56[8]
->本趟排序完成后:
2[1] 3[5] 4[9] 6[4] 8[3] 12[6] 7[7] 29[10] 45[2] 56[8]

->本趟排序枢轴记录是:6
high移动到4,交换low = 4处的记录为-1:(-1表示该位置为空)
2[1] 3[5] 4[9] -1[4] 8[3] 12[6] 7[7] 29[10] 45[2] 56[8]
->本趟排序完成后:
2[1] 3[5] 4[9] 6[4] 8[3] 12[6] 7[7] 29[10] 45[2] 56[8]

->本趟排序枢轴记录是:8
high移动到7,交换low = 5处的记录为7:(-1表示该位置为空)
2[1] 3[5] 4[9] 6[4] 7[7] 12[6] -1[7] 29[10] 45[2] 56[8]
low 移动到6,交换high = 7处的记录为12:(-1表示该位置为空)
2[1] 3[5] 4[9] 6[4] 7[7] -1[6] 12[6] 29[10] 45[2] 56[8]
high移动到6,交换low = 6处的记录为-1:(-1表示该位置为空)
2[1] 3[5] 4[9] 6[4] 7[7] -1[6] 12[6] 29[10] 45[2] 56[8]
->本趟排序完成后:
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]

快速排序后遍历顺序表([]内数字为其所在位置):
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]
请按任意键继续. . .

请选择您需要的功能:11
请按任意键继续. . .

请选择您需要的功能:8
排序前对顺序表进行遍历([]内数字为其所在位置):
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
选择排序后遍历顺序表([]内数字为其所在位置):
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]
请按任意键继续. . .

请选择您需要的功能:11
请按任意键继续. . .

请选择您需要的功能:9
排序前对顺序表进行遍历([]内数字为其所在位置):
2[1] 29[10] 4[9] 3[5] 6[4] 8[3] 7[7] 45[2] 12[6] 56[8]
归并排序后遍历顺序表([]内数字为其所在位置):
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]
请按任意键继续. . .

请选择您需要的功能:11
请按任意键继续. . .

请选择您需要的功能:10

排序前对顺序表进行遍历([]内数字为其所在位置):
2[1] 45[2] 8[3] 6[4] 3[5] 12[6] 7[7] 56[8] 4[9] 29[10]
堆排序后遍历顺序表([]内数字为其所在位置):
2[1] 3[5] 4[9] 6[4] 7[7] 8[3] 12[6] 29[10] 45[2] 56[8]
请按任意键继续. . .

请选择您需要的功能:12

--------------------------------
Process exited with return value 0
Press any key to continue . . .


下次文章会介绍各种内排序算法在大数据量情况下的运行效率比较。希望大家继续关注,再见。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐