【考研】数据结构常考九个排序算法关键代码汇总

34 篇文章 53 订阅
21 篇文章 1 订阅

CSDN话题挑战赛第2期
参赛话题:学习笔记

 前言

本文主要针对直接插入排序、希尔排序、快速排序、堆排序、归并排序等九个排序算法的关键代码进行汇总,方便复习。

各个排序算法的基本概念及相关习题等知识点,可见下方链接:

【考研】数据结构考点——直接插入排序_住在阳光的心里的博客-CSDN博客

 【考研】数据结构考点——折半查找和折半插入排序_住在阳光的心里的博客-CSDN博客

【考研】数据结构考点——希尔排序_住在阳光的心里的博客-CSDN博客_希尔排序dk

【考研】数据结构考点——直接选择排序_住在阳光的心里的博客-CSDN博客

【考研】数据结构考点——堆排序(含408真题)_住在阳光的心里的博客-CSDN博客

【考研】数据结构考点——冒泡排序(含408真题)_住在阳光的心里的博客-CSDN博客

【考研】数据结构考点——快速排序(重点,含408真题)_住在阳光的心里的博客-CSDN博客

【考研】数据结构考点——归并排序_住在阳光的心里的博客-CSDN博客

【考研】数据结构考点——链式基数排序_住在阳光的心里的博客-CSDN博客

排序算法中,也是考研常考的应用题型,可参考下方的第一个链接,题目讲解详细,方便复习。

可搭配以下链接一起学习:

【2023考研】数据结构常考应用典型例题(含真题)_住在阳光的心里的博客-CSDN博客

【考研】《数据结构》知识点总结.pdf_其它文档类资源-CSDN文库

目录

 前言

一、常考的排序算法代码

1、折半排序

2、快速排序

3、归并排序

4、堆排序

二、其他排序算法代码

5、直接插入排序

6、希尔排序

7、直接选择排序(简单选择排序)

8、冒泡排序

9、基数排序


一、常考的排序算法代码

//以下所有排序算法,若使用顺序存储结构,基本使用以下定义:

//数据元素类型定义
#define MAXSIZE 20    //顺序表的最大长度
typedef int KeyType;   //定义关键字类型为整型
typedef struct{   
    KeyType key;   //关键字项
    InfoType otherinfo;   //其他数据项
}RedType;    //记录类型
 
typedef struct {
    RedType r[MAXSIZE + 1];   // r[0]闲置或用做哨兵单元
    int length;    //顺序表长度
}SqList;   //顺序表类型

1、折半排序

//第一种
//对顺序表 L 做折半插入排序
void BInsertSort (SqList &L){
    for(i=2; i <= L.length; ++i){
        L.r[0] = L.r[1];    //将待插入的记录暂存到监视哨中
 
        //置查找区间初值
        low = 1;
        high = i-1;  
  
        //在r[low..high]中折半查找插入的位置   
        while (low <= high){            
            m = (low + high)/2;    //折半
            if(L.r[0].key < L.r[m].key) high = m - 1;   //插入点在前一子表
            else low = m + 1;   //插入点在后一子表
        }  

        for (j = i-1; j >= high+1; --j) 
            L.r[j+1] = L.r[j];    //记录后移
 
        L.r[high+1] = L.r[0];    //将 r[0] 即原 r[i],插入到正确位置
    }
}

//第二种
//对顺序表 L 做折半插入排序
void BInsertSort(int a[], int n) {  //n = a.size()
    int i, j, temp, mid, low, high;
    for (i = 1; i < n; ++i) {
        temp = a[i];    //将待插入的记录暂存到temp中

        //置查找区间初值
        low = 0;
        high = i - 1;

        //在a[low..high]中折半查找插入的位置   
        while (low <= high) {
            mid = (low + high) / 2;    //折半
            if (a[mid] > temp) high = mid - 1;   //插入点在前一子表
            else low = mid + 1;   //插入点在后一子表
        }

        for (j = i - 1; j >= high + 1; --j){
            a[j + 1] = a[j];    //记录后移
        }
        a[j + 1] = temp;    
    }
}

2、快速排序

// 对顺序表 L 中的子表 r[low..high] 进行一趟排序,返回枢轴位置
int Partition(SqList &L, int low, int high){
    L.r[0] = L.r[low];     //用子表的第一个记录做枢轴记录
    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;    //返回枢轴位置
}

//调用前置初值: low = 1; high = L.length;
//对顺序表 L 中的子序列 L.r[low..high] 做快速排序
void QSort (SqList &L, int low, int high){
    if (low < high) {     //长度大于1 
        pivotloc = Partition(L, low, high); //将L.r[low..high]一分为二,pivotloc是枢轴位置
        QSort(L, low, pivotloc - 1);     //对左子表递归排序
        QSort(L, pivotloc + 1, high);    //对右子表递归排序
    }
}
 
//对顺序表 L 做快速排序
void QuickSort(SqList &L){
    QSort(L, 1, L.length);
}

3、归并排序

// 将有序表 R[low..mid] 和 R[mid+1..high] 归并为有序表 T[low..high]
void Merge (RedType R[],RedType &T[], int low, int mid, int high){
    i = low;
    j = mid + 1;
    k = low;

    while(i <= mid && j<= high){      //将 R 中记录由小到大地并入 T 中
        if(R[i].key <= R[j].key) T[k++] = R[i++];
        else T[k++] = R[j++];
    }
      
    //只有一个 while 循环会被执行
    while(i <= mid) T[k++] = R[i++];      //将剩余的 R[low..mid] 复制到 T 中
    while(j <= high) T[k++] = R[j++];     //将剩余的 R[j..high] 复制到 T 中
}

// R[low..high] 归并排序后放入 T[low..high] 中
void MSort (RedType R[], RedType &T[], int low, int high){
    if (1ow == high) T[low] = R[low];
    else{
        mid = (low + high) / 2;        //将当前序列一分为二,求出分裂点 mid 

        //对子序列 R[low..mid] 递归归并排序,结果放入 S[low..mid]
        MSort (R, S, low, mid);  

        //对子序列 R[mid+1..high] 递归归并排序,结果放入 S[mid+1..high]
        MSort (R, S, mid+1,high) ;   

        //将 S[low..mid] 和 S[mid+1..high] 归并到 T[low..high]
        Merge (S, T, low, mid, high) ;    
    }
}

//对顺序表L做归并排序
void MergeSort (SqList &L){
    MSort(L.r, L.r, 1, L.length);
}

4、堆排序

//假设r[s+1..m]已经是堆,将r[s..m]调整为以 r[s] 为根的大根堆
void HeapAdjust (SqList &L, int s, int m){
    rc = L.r[s] ;
    for(j = 2*s; j <= m; j *= 2)     //沿 key 较大的孩子结点向下筛选
        if (j < m && L.r[j].key < L.r[j+1].key) 
            ++j;      // j 为 key 较大的记录的下标
        if(rc.key >= L.r[j].key) 
            break;     //rc应插入在位置s上
        L.r[s] = L.r[j];
        s = j;
    }
    L.r[s] = rc;     //插入
}
 
//把无序序列 L.r[1..n] 建成大根堆
void CreatHeap (SqList &L){
    n = L.length;
    for(i = n/2; i > 0; --i)     //反复调用HeapAdjust
        HeapAdjust (L, i, n);
}

//对顺序表L进行堆排序
void HeapSort (SqList &L){
    CreatHeap(L);     //把无序序列 L.r[1..L.length] 建成大根堆
    for(i = L.length; i > 1; --i){
        x = L.r[1]:     //将堆顶记录和当前未经排序子序列 L.r[1..i] 中最后一个记录互换
        L.r[1] = L.r[i];
        L.r[i] = x; 
        HeapAdjust(L, 1, i-1);      //将 L.r[1..i-1] 重新调整为大根堆
    }
}
 

二、其他排序算法代码

5、直接插入排序

//第一种写法
// 对顺序表 L 做直接插入排序
// 从后往前找
void InsertSort (SqList &L){     
    for(i = 2; i <= L. length; ++i){
        if(L.r[i].key < L.r[i-1].key){        //“<", 需将 r[i] 插入有序子表
            L.r[0] = L.r[i];       //将待插入的记录暂存到监视哨中
            L.r[i] = L.r[i-1];      //r[i-1] 后移
            for(j = i-2; L.r[0].key < L.r[j].key; --j)     //从后向前寻找插入位置
                L.r[j+1] = L.r[j];       //记录逐个后移,直到找到插入位置
            L.r[j+1] = L.r[0];     //将 r[0] 即原 r[i], 插入到正确位置
        }
    }
}

//第二种写法:
//直接插入排序
void InsertSort(int a[], int n) {      // n = a.size();
    int i, j, temp;
    for (i = 1; i < n; i++) {       //a[0]为枢轴
        if (a[i] < a[i - 1]) {
            temp = a[i];
            for (j = i; a[j - 1] > temp && j >= 1; j--) {
                a[j] = a[j - 1];
            }
            a[j] = temp;
        }
    }
}

6、希尔排序

//对顺序表L做一趟增量是dk的希尔插入排序
void ShellInsert (SqList &L,int dk){
    for (int i = dk + 1; i <= L.length; ++i){
        if(L.r[i].key < L.r[i-dk].key){    //需将 L.r[i] 插入有序增量子表
            L.r[0] = L.r[i];    //暂存在L.r[0]
 
            for(j = i - dk; j >0 && L.r[0].key < L.r[j].key; j -= dk){
                L.r[j+dk] = L.r[j];   //记录后移,直到找到插入位置
            }
            L.r[j+dk] = L.r[0];    //将 r[0] 即原 r[i] ,插入到正确位置 
        }
    }
}
 
//按增量序列 dt[0..t-1] 对顺序表 L 作趟希尔排序
void Shellsort(SqList &L, int dt[], int t){
    for(int k = 0; k < t; ++k)
       ShellInsert(L, dt[k]);    //一趟增量为 dt[t] 的希尔插入排序 
}
 
 

7、直接选择排序(简单选择排序)

//对顺序表 L 做简单选择排序
void SelectSort (SqList &L)
{
    for(i = 1; i < L.length; ++i){    //在L.r[i..L.length]中选择关键字最小的记录
        k = i;
        for (j = i+1; j <= L.length; ++j){
            if(L.r[j].key < L.r[k].key) 
                k = j;    //k指向此趟排序中关键字最小的记录
        }
 
        if (k != i){   //交换r[i]与r[k]
            t = L.r[i]; 
            L.r[i] = L.r[k]; 
            L.r[k] = t;
        }
    }
}

8、冒泡排序

//对顺序表 L 做冒泡排序
vold BubbleSort (SqList &L){
    // flag 用来标记某趟排序是否发生交换
    m = L.length - 1;  
    flag = 1;    
 
    while((m > 0) && (flag == 1)){
        flag = 0;     //flag置为0,如果本趟排序没有发生交换,则不会执行下趟摔序
        for (j = 1; j <= m; j++){
            if(L.r[j].key > L.r[j+1].key){
                flag = 1;     //flag 置为 1, 表示本趟排序发生了交换
 
                //交换前后两个记录
                t = L.r[j];
                L.r[j] = L.r[j+1];
                L.r[j+1] = t;
            }
        }
        --m;
    }
}
 

9、基数排序

#define MAXNUM_ KEY 8          //关键字项数的最大值
#define RADIX 10           //关键字基数,此时是十进制整数的基数
#define MAX_ SPACE 10000

typedef struct{
    KeyType keys[MAXNUM_KEY];       //关键字
    InfoType otheritems;       //其他数据项
    int next;
}SLCell;          //静态链表的结点类型

typedef struct{
    SLCell r[MAX_SPACE];      //静态链表的可利用空间,r[0]为头结点
    int keynum;             //记录的当前关键字个数
    int recnum;            //静态链表的当前长度
}SLList;         //静态链表类型

typedef int ArrType[RADIX]          //数组类型

//静态链表 L 的 r 域中记录已按(keys[0], ..., keys[i-1]有序
//本算法按第 i 个关键字 keys[i] 建立 RADIX 个子表,使同子表中记录的 keys[i] 相同
//f[0..RADIX-1] 和 e[0..RADTX-1] 分别指向各子表中第一个和最后一个记录
void Distribute(SLcell &r, int i, ArrType &f, ArrType &e){
    for(j = 0; j < RADIX; ++j) f[j] = 0;       //各子表初始化为空表
    for(p = r[0].next; p; p = r[p].next){
        j = ord(r[p].keys[i]);     //将记录中第 i 个关键字映射到 [0..RADIX-1]

        if(!f[j]) f[j] = p;
        else r[e[j]].next = p;

        e[j] = p;       //将P所指的结点插入第 j 个子表中
    }
}


// 本算法按 keys[i] 自小至大地将 f[0..RADIX-1] 所指各子表依次链接成一个链表
// e[0..RADIX-1] 为各子表的尾指针
void Collect (SLCell &r, int i, ArrType f, ArrType e){
    for (j = 0; !f[j]; j = succ(j));     //找第一个非空子表,succ 为求后继函数

    r[0].next = f[j]; 
    t = e[j];     //r[0].next 指向第一个非空子表中第一个结点

    while (j < RADIX){
        for(j = succ(j); j < RADIX-1 && !f[j]; j = succ(j));   //找下一个非空子表

        if(f[j]){   //链接两个非空子表
            r[t].next = f[j]; 
            t = e[j];
        }
    }

    r[t].next = 0;     // t 指向最后一个非空子表中的最后一个结点
}

// L 是采用静态链表表示的顺序表
// 对 L 做基数排序,使得 L 成为按关键字自小到大的有序静态链表,L.r[0]为头结点
void Radixsort(SLList &L){
    for(i = O; i < L.recnum; ++i) L.r[i].next = i + 1; 
    L.r[L.recnum].next = 0;    //将 L 改造为静态链表

    for(i = O; i < L.keynum; ++i){     //按最低位优先依次对各关键字进行分配和收集
        Distribute(L.r, i, f, e);     //第i趟分配
        Collect(L.r, i, f, e);      //第i趟收集
    }
}


  • 2
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

住在阳光的心里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值