数据结构_study(八)

排序

排序:(记录对应的)关键字递增或递减 有序序列

n个记录的序列:{r1,r2………,rn},
对应的关键字:{k1,k2,……kn},
需确定 1,2,……,n 的一种排列 p1,p2,………,pn,使其相应的关键字满足 kp1<=kp2<=……<=kpn(非递减或非递增)关系
即得一个按关键字有序的序列{rp1,rp2,……,rpn},这样的操作就称为排序。

排序:线性表的一种操作
输入:记录集合,输出:记录集合
依据:关键字之间的大小关系
同一个记录集合,针对不同的关键字(主关键字、次关键字、若干数据项的组合)排序,可以得到不同序列

稳定性

排序方法稳定:两个相等的关键字不会因为排序逆序
排序方法不稳定:两个相等的关键字因为排序逆序
在这里插入图片描述

结构和函数

//排序用的顺序表结构
#define MAXSIZE 10 /*用于要排序数组个数最大值,可根据需要修改*/
typedef struct
{
    int r[MAXSIZE + 1]; /*用于存储要排序数组,r[0]用作哨兵或临时变量*/
    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;
}

内排序和外排序

外排序:排序的记录个数太多(不能同时放在内存),需要在内外存之间多次交换数据

内排序:待排序的所有记录放在内存
性能影响:
1、时间性能,比较和移动
2、辅助空间,算法需要的,除待排序元素以外的其他存储空间
3、算法复杂度
分为:插入排序,交换排序,选择排序,归并排序
在这里插入图片描述

简单算法

从小往大排序

冒泡(交换)

初级版:每一个关键字都和后面的每一个关键字比较,大则交换
在这里插入图片描述

冒泡排序:循环(数组长度)次,每次从数组末尾开始,更小元素往前冒泡(交换),最小值会冒泡到最前端
在这里插入图片描述

优化:增加一个标记,一次循环中没有发生冒泡说明序列已有序,判断标记结束循环

优化版本 时间复杂度 O(n2):
最好情况:n-1次比较,没有数据交换,O(n)
最坏情况:逆序, (n-1)+(n-2)+…+2+1=n*(n-1)/2 次比较,相等数量数据交换;

简单选择

每次选出 i 到数组末尾最小的元素,和 i 交换

总时间复杂度 O(n2) :
比较次数 (n-1)+(n-2)+…+2+1=n*(n-1)/2
交换数据少, 次数 n-1,略优于冒泡

在这里插入图片描述

直接插入

把记录插入到有序表中,得到记录+1的有序表

总时间复杂度 O(n2):
最好情况:比较(n-1)次
最坏情况:
比较次数:n+(n-1)+…+2=(n+2)* (n-1)/2
移动次数 (n+1)+n+…+3=(n+4)*(n-1)/2
平均:(好坏概率相同)比较和移动次数n2/4,略优于冒泡和简单选择
在这里插入图片描述

改进算法

希尔(插入排序升级版)

基本有序:小的关键字基本在前面,大的基本在后面,不大不小的基本在中间

希尔排序:(相距某个“增量”的)记录组成一个子序列,对子序列直接插入排序

跳跃分割 保证结果基本有序,不是局部有序

时间复杂度O(n3/2)
增量选取非常关键,研究提供的增量序列 dlta[k]=2t-k+1-1,(0<=k<=t<=logz(n+1)向下取整)
最后一个增量值必须=1

跳跃移动,不稳定
在这里插入图片描述

堆(选择排序升级版)

:完全二叉树,大/小顶堆
大顶堆:每个结点都>=左右孩子结点
小顶堆:每个结点都<=左右孩子结点

根结点一定是堆中所有结点的最大(小)值

一棵完全二叉树,
i=1:结点i是二叉树的根,无双亲;
i>1,则其双亲是结点i/2向下取整。
有 n个结点的二叉树,i<=n/2向下取整

层序遍历编号i,n个结点,1<=i<=n/2向下取整
大顶堆:ki>=k2*i(左) ,ki>=k2*i+1(右)
小顶堆:ki<=k2*i ,ki<=k2*i+1
存入数组
在这里插入图片描述

堆排序:待排序列,构造大顶堆,得到最大值(根),移除(与堆层序遍历末尾元素交换),重复构造大顶堆和移除操作

堆排 时间复杂度 O(nlogn):
构件堆时间复杂度O(n)
第i次取堆顶,重建堆需要O(logi),取n-1次,共O(nlogn)
空间复杂度:只有一个暂存单元用来交换

跳跃比较交换:不稳定排序

初始构建堆需要比较多次,待排序列个数少用比较浪费

在这里插入图片描述
在这里插入图片描述

归并

归并排序:n个记录,看作n个有序子序列,序列长度为1两两归并,得到(n/2向上取整)个长度为2或1的有序子序列;重复两两归并,直到得到长度为n的有序序列
在这里插入图片描述
Merge
在这里插入图片描述
递归归并排序
在这里插入图片描述
非递归归并排序
在这里插入图片描述

时间复杂度:合并消耗O(n),log2n次合并,共O(nlogn)
非递归省略递归的时间
空间复杂度:
递归:辅助空间n,递归时深度为log2n的栈空间
非递归:只有辅助空间O(n)

快排(交换排序升级版)

枢轴:关键字,左边的值比它小,右边的值比它大

partition函数:用第一个关键做枢轴,将数组调整为枢轴成立
在这里插入图片描述
时间复杂度:
最优情况,O(nlogn),递归次数,对应n个结点平衡二叉树 深度 log2n向下取整+1;
最坏情况,O(n2),n-1次递归,每次需要比较n-i次
平均 O(nlogn)

空间复杂度:
最优情况,递归次数,O(logn);
最坏情况,n-1次递归,O(n)
平均 O(nlogn)

跳跃进行,不稳定

优化

1、优化选取枢轴
枢轴太大或太小,都会影响性能,(完全二叉树和斜二叉树的深度区别)

  • 随机枢轴
  • 三数取中:取3个关键字排序,取中间数,适合小数组
  • 九数取中:3次取样,每次取3个,3个中数再取中数,适合大数组

2、优化不必要的交换,替换代替交换
在这里插入图片描述
3、优化小数组的排序:数组小(长度小于某一个值)时直接插入更好
4、优化递归:while代替if,减少递归
在这里插入图片描述

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值