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

上次我们介绍了二叉排序树的实现,这次介绍各种排序算法的实现。

还是老规矩:

程序在码云上可以下载。
地址:https://git.oschina.net/601345138/DataStructureCLanguage.git

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

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

直接看代码吧:


//*************************引入头文件****************************
#include 
#include    

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

#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//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 . . . 

下次文章会介绍各种内排序算法在大数据量情况下的运行效率比较。希望大家继续关注,再见。

你可能感兴趣的:(学习笔记)