数据结构【排序】

排序

算法动画模拟

插入排序

插入排序

思想:(从小到大)就是和之前的元素依次进行比较,如果当前值小于 前面的值,那么将当前值往前插入,然后前面的序列都依次往后移动一位。
在这里插入图片描述
在这里插入图片描述

时间复杂度:o(n²)
链表实现在插入的时候,相对于方便实现。

希尔排序(手算)

特性:不稳定,只能基于顺序表,不能链表
视频地址
每次都设置增量d,然后根据增量将 数据表分为几块,进行对比交换,建议初始d为:n/2,每次都除以2。直到d=1。
d=1时,整体基本有序,然后再进行一次插入排序,整体结束
在这里插入图片描述

交换排序(要会写代码)

冒泡排序

思想:相邻两个节点进行比较,根据大小进行交换位置。
特性:每一轮for排序都能确定一个指的位置
代码:

 //从小到大
 void bubbleSort(int array[],int length){
    for (int i = 0; i < length; i++)
    {
        int flag = 1;//如果此次循环没有交换位置,表示数组基本已经有序了,可以直接跳出
        for (int j = length-1; j > i; j--)
        {
            if(array[j]<array[j-1]){
                int temp = array[j];
                array[j] = array[j-1];
                array[j-1] = temp;
                flag = 0;
            }
        }
        if(flag){
            break;
        }
        
    }
    toString(array,length);
    
 }

快速排序

视频地址

思想:首先选出一个枢纽(pivot)值一般为第一个,然后定义low和high,依次将数组划分为两半,左边<=枢纽值,右边>=枢纽值。 然后再依次左边继续划分,右边继续划分,类似于排序二叉树的逻辑,详情看下图和代码
当low和high相等表示左右两边已经基本一次排序完毕

特性:时间复杂度:O(n²) ,空间复杂度:O(h),不稳定

/**
 * 快速排序:一阶段排序,从小到大
 * return: 枢纽值 
**/
 int quickOnceSort(int array[],int low,int high){
        int pivot = array[low];
        while(low<high){
            while(low<high && array[high]>pivot){
                high--;
            }
            array[low] = array[high];
            while (low<high && array[low] < pivot)
            {
                low++;
            }
            array[high] = array[low];
            
        }
        //将枢纽值进行替换到中间,按照逻辑其实使用low或者high都可以,因为low和high目前是一样的
        array[low] = pivot;
        return low;
 }
 /**
  * 快速排序 :简化递归排序左右两个模块
  *  其实快速排序递归操作,类似于二叉排序树结构,初次根据枢纽值,分为左右模块,然后再根据左边进行依次递归分离,右边依次分离..
 **/
 void quickSort(int array[],int low,int high){
    if(low<high){
        int pivot = quickOnceSort(array,low,high);
        quickSort(array,low,pivot-1);
        quickSort(array,pivot+1,high);
    }
    //打印
    toString(array,5);

 }

处理过程逻辑

1、
在这里插入图片描述
2、
在这里插入图片描述
3、
在这里插入图片描述
4、
在这里插入图片描述

选择排序

选择排序:每一趟在待排序元素中选取关键字最小(或最大)的元素加入有序子序列

简单选择排序

每次遍历最小的或者最大的放在头部,然后依次类推一直扫描n-1个元素,最后一个元素就不用扫描了
特性:不稳定,时间复杂度o(n²),空间O(n)
在这里插入图片描述

代码实现:

堆排序

补充: 当前节点i,左孩子 2i,右 2i+1 ,父节点i/2
物理视角:它就是一个数组
逻辑角度:它就是一个二叉树
大根堆: 就是左<中间节点,中间节点>右节点
小根堆: 就是 中间节点<左节点,中间节点<右节点
特性:建立堆o(n)时间复杂度
构成大根堆思路:从当前叶子节点开始进行处理,n/2,然后先进行判断当前 节点的左孩子和右孩子谁更大,然后再由更大的和当前节点进行比较,如果进行交换,然后再次循环查找交换后的左孩子右孩子节点再次进行对比,依次到数组结尾

大根堆构成后,然后收尾交换,然后再继续大根堆调整

堆的删除和插入操作

1、小跟堆插入:当插入一个数字默认是插入到数组的最后,然后再进行比较,直接一直上升比较它的父节点,因为左或者右节点肯定是已经调整好的。、
2、删除操作:删除分支节点,那么默认由 队尾进行代替。如删除13 那么由46进行代替,然后再进行调整。 这次调整的话则 需要节点的 左右孩子先进行对比,然后再由大的或者小的和当前节点对比调整
在这里插入图片描述

归并排序

归并排序:将两个或者多个有序的序列 合并为一个有序序列
结论:
1、m路归并,选出一个元素进行归并关键字对比至少m-1次
2、空间O(n) 、时间O(nlogn) 、稳定

在这里插入图片描述

考试一般考的都是二路归并

二路归并就是将相邻的两个 元素 认为是两个数组,然后进行排序,排序完成后进行合并成一个数组,后续也是进行对比两个相邻 ** 的数组**,然后再进行合并
在这里插入图片描述

基数排序(手算)

基数排序:一般适用于数据量比较比较大的情况,(如很多数据的身份证之类)根据 元素的 个十百千位数进行计算
特性:基数排序大多都是根据链式存储进行实现的,数组+队列的方式,r队列个数也就是数组
因此空间复杂度O®,时间O(d(n+r))稳定
先根据数组中元素 个位 进行排序,后序再根据十位…
第一次:个位
 第一次个位收集排序
第二次:十位
第二次手机十位排序
第三次:百位
第三次百位排序

外部排序

外部排序:也就是因为数据量比较的多的情况,数据大部分都存储在磁盘上,而需求对数据进行排序,那么只能一块一块的取出部分数据读取到内存中进行排序。
外部排序:也就是基于归并排序进行实现

实例下图

在这里插入图片描述

一、先进行阶段性的排序(两个相邻的视为一个)

在这里插入图片描述
二、基本排序完成,两个相邻的数组进行 合并
在这里插入图片描述
第二次合并,4-4
在这里插入图片描述
后续依次…

最佳归并树(手算)

最佳归并树,类似于 哈夫曼树进行计算,树的权值,只不过这次的话是根据 每次(路段)【也就是数组节点】的数量作为节点数。
注意: 如果需要构造k叉 最佳归并树,而 归并段 无法构成严格的k叉归并树,那么需要进行添加 **虚段 **,然后再进行构建。

最佳归并树示例

二路归并: R1–R2–R3–R4–R5

下图R代表一个 **归并段 **
在这里插入图片描述

由上图可得 最佳带权路径WPL=34 也就是最佳读磁盘次数为34次
读写磁盘次数为:68

三路归并

归并段:
在这里插入图片描述

最佳树:
在这里插入图片描述

虚段

几路归并:k ;

判断是否需要增加虚段:

  • 若()

计算虚段示例
如:19个归并段,8路排序
①(19-1) % (8-1) = u , u=4 ,表明需要添加虚段,
②(8-1)-4 = 3 ,表示需要添加4个虚段

需要补充虚段,最佳归并路示例

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值