美文网首页
常见的排序

常见的排序

作者: ChenL | 来源:发表于2020-05-20 21:08 被阅读0次

排序:
假设含有n个记录的序列为(r1,r2,.....,rn). 其相应的关键字分别为{k1,k2,......,kn}. 需确定1,2,......,n 的⼀种排序p1,p2,......pn. 使其相应的关键字满⾜kp1 <= kp2 <= ...... <= kpn ⾮递减(或⾮递增)关系. 即使得到序列成为⼀个按关键字有序的序列(rp1,rp2,...,rpn).这样得出操作称为排 序。

1)内排序:是在排序整个过程中,待排序的所有记录全部被放置在内存中;
2)外排序:由于排序的记录个数太多,不能同时放置在内存,整个排序过程需要在内外存之间多次交换数据才能进⾏。

1、排序的数据结构

//1.排序算法数据结构设计
//用于要排序数组个数最大值,可根据需要修改
#define MAXSIZE 10000
typedef struct
{
    //用于存储要排序数组,r[0]用作哨兵或临时变量
    int r[MAXSIZE+1];
    //用于记录顺序表的长度
    int length;
}SqList;

2、排序常用交换函数实现

//交换L中数组r的下标为i和j的值
void swap(SqList *L,int i,int j)
{
    int temp=L->r[i];
    L->r[i]=L->r[j];
    L->r[j]=temp;
}

3、冒泡排序

冒泡排序重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成,理论上总共要进行n(n-1)/2次交换。

void BubbleSort(SqList *L){
    int i,j;
    for (i = 1; i < L->length; i++) {
        //注意:j是从后面往前循环
        for (j = L->length-1; j>=i; j--) {
            
            //若前者大于后者(注意与上一个算法区别所在)
            if(L->r[j]>L->r[j+1])
                //交换L->r[j]与L->r[j+1]的值;
                swap(L, j, j+1);
        }
    }
}

4、选择排序

简单选择排序是通过 n-i次关键词的比较,从n-i-1个记录中找到关键字最小的记录,并和i个记录进行比较。

void SelectSort(SqList *L){
  
    int i,j,min;
    for (i = 1; i < L->length; i++) {
        //将当前下标假设为最小值的下标
        min = i;
        //循环比较i之后的所有数据
        for (j = i+1; j <= L->length; j++) {
            //如果有小于当前最小值的关键字,将此关键字的下标赋值给min
            if (L->r[min] > L->r[j]) {
                min = j;
            }
        }
        //如果min不等于i,说明找到了最小值,则交换2个位置下的关键字
        if(i!=min)
            swap(L, i, min);
    }
}

5、直接插入排序算法(对顺序表L进行直接插入排序)

直接插入排序算法是将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增1的有序表。

void InsertSort(SqList *L){
    int i,j;
    //L->r[0] 哨兵 可以把temp改为L->r[0]
    int temp=0;
    
    //假设排序的序列集是{0,5,4,3,6,2};
    //i从2开始的意思是我们假设5已经放好了. 后面的牌(4,3,6,2)是插入到它的左侧或者右侧
    for(i=2;i<=L->length;i++)
    {
        //需将L->r[i]插入有序子表
        if (L->r[i]<L->r[i-1])
        {
            //设置哨兵 可以把temp改为L->r[0]
            temp = L->r[i];
            for(j=i-1;L->r[j]>temp;j--)
                    //记录后移
                    L->r[j+1]=L->r[j];
            
            //插入到正确位置 可以把temp改为L->r[0]
            L->r[j+1]=temp;
        }
    }
}

6、希尔排序 (对顺序表L希尔排序)

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。该方法实质上是一种分组插入方法。

void shellSort(SqList *L){
    int i,j;
    int increment = L->length;
    
    //0,9,1,5,8,3,7,4,6,2
    //当increment 为1时,表示希尔排序结束
    do{
        // 增量序列
        increment = increment/3+1;
        //i的待插入序列数据 [increment+1 , length]
        for (i = increment+1; i <= L->length; i++) {
            // 如果r[i] 小于它的序列组元素则进行插入排序,例如3和9. 3比9小,所以需要将3与9的位置交换
            if (L->r[i] < L->r[i-increment]) {
                // 将需要插入的L->r[i]暂时存储在L->r[0].和插入排序的temp 是一个概念;
                L->r[0] = L->r[i];
                
                // 记录后移
                for (j = i-increment; j > 0 && L->r[0]<L->r[j]; j-=increment) {
                    L->r[j+increment] = L->r[j];
                }
                
                // 将L->r[0]插入到L->r[j+increment]的位置上;
                L->r[j+increment] = L->r[0];
            }
        }
    }while (increment > 1);
}

7、 堆排序

堆结构是具有下面性质的完全二叉树;每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于等于其左右孩子的结点的值,称为小顶堆。
基本思想:
将待排序的序列构成一个大顶堆,此时,整个序列的最大值就是堆顶的根结点,将它与堆数组的末尾元素交互,此时末尾元素就是最大值;
将剩下的n-1个序列重新构成一个堆,这样就会得到n个元素的次大值,重复执行,就能得到一个有序队列。

大顶堆调整函数
条件: 在L.r[s...m] 记录中除了下标s对应的关键字L.r[s]不符合大顶堆定义,其他均满足;
结果: 调整L.r[s]的关键字,使得L->r[s...m]这个范围内符合大顶堆定义.

void HeapAjust(SqList *L,int s,int m){
    int temp,j;
    temp = L->r[s];
    for (j = 2 * s; j <=m; j*=2) {
        if(j < m && L->r[j] < L->r[j+1])
            ++j;
        if(temp >= L->r[j])
            break;
        L->r[s] = L->r[j];
        s = j;
    }
    L->r[s] = temp;
}

void HeapSort(SqList *L){
    int i;
    //对非叶子的根结点调整.
    for(i=L->length/2; i>0;i--){
        HeapAjust(L, i, L->length);
    }
    for(i = L->length; i > 1; i--){
        //将堆顶记录与当前未经排序子序列的最后一个记录进行交换;
        swap(L, 1, i);
        //将L->r[1...i-1]重新调整成大顶堆;
        HeapAjust(L, 1, i-1);
    }
}

相关文章

  • LeetCode大全

    1.常见排序算法: 常见的排序算法:冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序、计数排序、...

  • Python知识点:常见算法的python实现

    提到排序算法,常见的有如下几种:冒泡排序、选择排序、插入排序、快速排序、堆排序、归并排序、希尔排序;查找算法最常见...

  • 实现几种常见排序方法

    Java实现几种常见排序方法 日常操作中常见的排序方法有:冒泡排序、快速排序、选择排序、插入排序、希尔排序,甚至还...

  • 常见排序的java实现

    常见排序的java实现 常见排序java实现 插入排序(二分插入排序) 希尔排序 快速排序(三数中值快排) 冒泡排...

  • 排序算法

    常见的排序算法 常见的排序算法有:插入、希尔、选择、冒泡、归并、快速、堆排序。。。 插入排序 算法步骤一、从数组的...

  • 常见的10种排序算法与C#实现

    常见的排序算法——常见的10种排序[https://www.cnblogs.com/flyingdreams/p/...

  • IOS常见算法

    常见算法: 快速排序: 选择排序: 冒泡排序: 测试代码:

  • 排序

    排序是实际运用中比较常见的情况。计算机界也对排序进行了很深入的研究。常见的排序算法有:快速排序、归并排序、插入排序...

  • 记录几个常见的排序算法

    常见的排序有:快速排序、冒泡排序、希尔排序、选择排序、插入排序、归并排序 冒泡排序: 插入排序: 选择排序: 希尔...

  • 排序算法

    排序算法 冒泡排序 选择排序 插入排序 快速排序(最常见) 希尔排序 归并排序 源码:Sorting 冒泡排序 冒...

网友评论

      本文标题:常见的排序

      本文链接:https://www.haomeiwen.com/subject/scsbohtx.html