【算法与数据结构---排序算法】

选择排序

选择最小值与0位置元素交换、次小值与1位置元素交换,次次小值与2位置元素交换。。。。。
时间复杂度O(N^2), 空间复杂度O(1) 不稳定

冒泡排序

两个两个比较。
增续:第i个和第(i+1)个比较,若a[i] > a[i+1],交换顺序,i++
时间复杂度O(N^2), 空间复杂度O(1) ,稳定


异或运算:相同为0,不同为1,可视作无进位相加(二进制相加 );满足交换律、结合律
a ^ b ^ b = a (b ^ b = 0, 0 ^ a = a)
交换方法

swap(a, b){//a、b地址不一样
  a = a ^ b;
  b = a ^ b;
  a = a ^ b;
}

数组长度为n,有两种数a, b为奇数个,其他数偶数个,怎么得到这两个数?
1.将所有数异或,得到res = a ^ b;
2.res的第 i 位一定为1,说明a或b在第 i 位一定为1,另一个为0, 将原数组中第i位为1的数全部异或,就可以得到a或者b
(a ^ (~a + 1))= a 的最右侧的1


插入排序

1.从第一个元素开始,该元素可以认为已经被排序
2.取下一个元素tem,从已排序的元素序列从后往前扫描
3.如果该元素大于tem,则将该元素移到下一位
4.重复步骤3,直到找到已排序元素中小于等于tem的元素
5.tem插入到该元素的后面,如果已排序所有元素都大于tem,则将tem插入到下标为0的位置
6.重复步骤2~5
—————————————-———
原文链接: https://blog.csdn.net/weixin_50886514/article/details/119045154

时间复杂度:O(N^2) (按照算法可能遇到的最差情况估计)
空间复杂度O(1) ,稳定


二分查找
在一个有序数组中找到数num:从中间开始找
时间复杂度O(log N)
在一个无序数组中找到局部最值也可以用二分


对数测试器:判断算法写得对不对
在这里插入图片描述
子问题等规模时可以用master公式计算时间复杂度
a:子问题调用次数
T(N/b):子问题的规模
O(N^d):除子问题外,其他代码块的复杂度

归并排序

先将前半部分排好序,再将后半部分排好序,最后将两部分合并
时间复杂度O(N*logN) ,空间复杂度O(N) ,稳定

快速排序

以数组最后一个数a[N]为基准,将小于a[N]的数放左边,大于a[N]的数放右边,然后左右两边各自递归重复这一过程
i = 0; L是小于区的指针,小于区为[0,L];R是大于区的指针,大于区为[R,N-1]。(数组范围0~N-1)
a[i]小于a[N]时,将a[i]与a[L+1]交换,L++;a[i]=a[N]时,i++;a[i]>a[N]时,a[i]与a[R-1]交换,R–,i不变;只要对左右两侧两个区递归,中间等于区不用递归
O( N^2 )

  • 更快的快排:
    不用数组最后一个作为基准,用随机选的数作为基准
    时间复杂度O(N*logN),空间复杂度:O(logN), 不稳定

堆排序

  • 数组从0开始连续L个数够成二叉树,第i个元素的左子树是第(2i+1),右子树是(2i+2),父节点是((i-1)/2)(二叉树层序遍历)

  • 大根堆:根节点是最大的数
    小根堆:根节点是最小的数
    题目:一个序列,随时可以找到中位数。
    算法思想:准备一个大根堆,一个小根堆,第一个数入大根堆,接下来每个数和大根堆的根比较,若小于等于大根堆的根,则入大根堆,否则入小根堆;当大、小根堆的长度差为2时,较长的堆的根移到较小的堆。若序列长度为偶数,则大、小根堆的两根平均为中位数,若奇数,较长的堆的根为中位数。

  • heap insert过程:
    1. 每次给一个数,放入堆中,形成大根堆。将每次得到的新数a[i]和它的父节点(a[(i-1)/2])比较,若大于则交换,交换后继续和父节点比较,直到新插入的值小于等于其父节点。
      在这里插入图片描述
  1. heapify:若要求去出堆中最大值,剩余元素仍保持大根堆结构:最大值在根节点,为a[0],将a[0]取出,并将最后一个元素放到[0]位置,并用左右孩子中的最大值和其比较,若新的a[0]比字节的小,则交换位置
    在这里插入图片描述
    O(logN)
  • 堆排序
    大根堆的根节点与数组最后一个位置的元素交换,并将heapsize–,即将原来的根节点排出堆,排出堆的就是已经排好序的,然后将新的堆重新排成大根堆,重复前面的过程,最终将数组递增排序。
    时间复杂度O(NlogN),空间复杂度O(1),不稳定

在这里插入图片描述

  • Java小根堆的类:
    PriorityQueue heap = new PrioiityQueue<>();//默认小根堆的结构
    扩容的代价O(logN),不支持调整已经形成的堆,若有调整堆的需求,最好自己手写一个堆

无比较排序

适用于数据范围较小的情况

  1. 计数排序
    哈希表,key为数据范围内所有值,value为该数据出现的次数,按照key的顺序和value次数打印数据
  2. 基数排序
    一组不超过三位、十进制的数组(低于三位的高位补零),升序排列:
    1. 将所有数按照个位数依次放入对应的桶中(个位为i就放入i号桶),按桶号升序、FILO的顺序取出,再次按照十位数将重新排列的数放入桶中、取出,最后按照百位数将重新排列的数放入桶中、取出,数组已按升序排列。
    2. 另一种入桶出桶:准备一个哈希表hm,key值为0~9,value计数。若第 i 个数的个位数为 x ,则哈希表中 x 对应的值加一,遍历一遍数组后,将哈希表的value值累加为个位数小于等于 x 的数有多少个,即hm.get(x) = hm.get(x) + hm.get(x - 1) + … +hm.get(0). 准备一个和原数组长度一样的空数组,从右到左遍历原数组,个位为 x 的数应放到空数组中索引为(hm.get(x) - 1)的位置,放入后,hm.get(x)–. 重复以上过程直到数组中最大值的最高位。
  • 排序的稳定性
    数组中含有多个值相同的元素,排序后,原来相同值的元素的先后次序是否也交换了
    稳定的排序算法:冒泡排序、插入排序、归并排序(相等时先拷贝左边的)、计数排序、基数排序
    不稳定的排序算法:选择排序、快速排序、堆排序
  • 最常用的是快速排序;当需要稳定但对空间复杂度不设限时用归并排序;当对空间限制但不要求稳定时用堆排序(目前没有时间复杂度小于O(NlogN)以下的、基于比较的排序算法;时间复杂度为O(NlogN)的情况下,目前没有在空间复杂度O(N)以下实现稳定的排序算法)
  • 工程上对排序的改进:
    1. 充分利用O(N*longN) 和 O(N^2)排序各自的优势
      例如:综合排序,大范围时快速排序,大致排好序后,大样本中长度小的子样本用插入排序
    2. 稳定性的考虑
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值