直接插入排序

直接插入排序(Straight Insertion Sorting)的基本思想:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
直接插入排序是一种稳定的排序方法,最好的时间复杂是O(n)也就是已经排好的序列,最差的时间复杂度是O(n^2)逆序

    //插入排序是一种稳定的排序方法,最好的时间复杂是O(n)也就是已经排好的序列,最差的时间复杂度是O(n^2)逆序public void insertSort(int nums[]){int tmp;for(int i=1;i<nums.length;i++){int j=i;while (j>0 && nums[j]<nums[j-1]){tmp=nums[j];nums[j]=nums[j-1];nums[j-1]=tmp;j--;}}}

希尔排序

  • 希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。
  • 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

算法思想

对于直接插入排序问题,数据量巨大时。将数的个数设为n,取奇数k=n/2,将下标差值为k的数分为一组,构成有序序列。再取k=k/2 ,将下标差值为k的书分为一组,构成有序序列。重复第二步,直到k=1执行简单插入排序。

希尔排序是一种非常不稳定的排序方法,它的时间复杂度为O(n^(1.3—2))

//希尔排序是一个不稳定的排序算法,它的时间复杂度为O(n^(1.3—2))public void shellSortHelper(int nums[],int incr){int tmp;for(int i=incr;i<nums.length;i+=incr){int j=i;while (j>0 && nums[j]<nums[j-incr]){tmp=nums[j];nums[j]=nums[j-incr];nums[j-incr]=tmp;j-=incr;}}}//希尔排序public void shellSort(int nums[]){for(int i=nums.length/2;i > 0;i/=2){shellSortHelper(nums,i);}}

选择排序

  1. 常用于取序列中最大最小的几个数时。
    (如果每次比较都交换,那么就是交换排序;如果每次比较完一个循环再交换,就是简单选择排序。)

  2. 遍历整个序列,将最小的数放在最前面。

  3. 遍历剩下的序列,将最小的数放在最前面。

  4. 重复第二步,直到只剩下一个数。

选择排序的时间复杂度为O(n^2) 选择排序不是一个稳定的排序

//交换排序是一种稳定的排序方法,最好最坏的时间复杂度都是O(n^2)public void swapSort(int nums[]){int tmp;for(int i=0;i<nums.length;i++){for(int j=i+1;j<nums.length;j++){if(nums[i]>nums[j]){tmp=nums[j];nums[j]=nums[i];nums[i]=tmp;}}}}//选择排序是一种不稳定的排序方法,最好最坏的时间复杂度都是O(n^2)public void selectSort(int nums[]){for(int i=0;i<nums.length;i++){int values=nums[i];int position=i;for(int j=i+1;j<nums.length;j++){if(nums[j]<values){values=nums[j];position=j;}}//swapnums[position]=nums[i];nums[i]=values;}}

冒泡排序

很简单,用到的很少,据了解,面试的时候问的比较多!将序列中所有元素两两比较,将最大的放在最后面。将剩余序列中所有元素两两比较,将最大的放在最后面。重复第二步,直到只剩下一个数。

冒泡排序的时间复杂度为O(n^2) 冒泡排序是一个稳定的排序

    //冒泡排序 一种稳定的排序算法,最好最坏的时间复杂度都是O(n^2)public void bubbleSort(int nums[]){int tmp;for(int i=0;i<nums.length;i++){for (int j=0;j<nums.length-i-1;j++){if(nums[j]>nums[j+1]){tmp=nums[j+1];nums[j+1]=nums[j];nums[j]=tmp;}}}}

快速排序

要求时间最快时。

  1. 选择第一个数为p,小于p的数放在左边,大于p的数放在右边。
  2. 递归的将p左边和右边的数都按照第一步进行,直到不能递归。

快速排序是由一种不稳定的排序算法,最好的时间复杂度是O(nLogN),最差时间复杂度是O(n^2)

 //快速排序是由一种不稳定的排序算法,最好的时间复杂度是O(nLogN),最差时间复杂度是O(n^2)private void quickSortHelper(int nums[],int start,int end){if(start>end) return;int high=end;int low=start;int target=nums[start];while (low<high){while (low<high && nums[high]>=target){high--;}nums[low]=nums[high];while (low<high && nums[low]<=target){low++;}nums[high]=nums[low];}nums[low]=target;quickSortHelper(nums,start,low-1);quickSortHelper(nums,low+1,end);}public void quickSort(int nums[]){quickSortHelper(nums,0,nums.length-1);}

归并排序

速度仅次于快速排序,内存少的时候使用,可以进行并行计算的时候使用。

  1. 选择相邻两个数组成一个有序序列。
  2. 选择相邻的两个有序序列组成一个有序序列。重复第二步,直到全部组成一个有序序列。

归并排序,是一种稳定的排序是算法这个算法的时间复复杂度都是O(NlogN)

    //归并排序,是一种稳定的排序是算法这个算法的时间复复杂度都是O(NlogN)public void mergeSrot(int nums[],int start,int end){if(start>=end) return;int mid=(start+end)/2;mergeSrot(nums,start,mid);mergeSrot(nums,mid+1,end);mergeSrotHelper(nums,start,mid,end);}//  将两个有序序列归并为一个有序序列(二路归并)private void mergeSrotHelper(int[] nums, int start, int mid, int end) {int[] arr=new int[end+1];int low=start;int left=start;int center=mid+1;while (left<=mid && center<=end){arr[low++] = nums[left] <= nums[center] ? nums[left++] : nums[center++];}while (left<=mid){arr[low++]=nums[left++];}while (center<=end){arr[low++]=nums[center++];}for(int i=start;i<=end;i++){nums[i]=arr[i];}}

堆排序

对简单选择排序的优化。

  1. 将序列构建成大顶堆。
  2. 将根节点与最后一个节点交换,然后断开最后一个节点。
  3. 重复第一、二步,直到所有节点断开。
  //堆排序private boolean isLeaf(int nums[],int pos){//没有叶子节点return pos*2+1>=nums.length;}private void swap(int[] nums,int pos1,int pos2){int tmp;tmp=nums[pos2];nums[pos2]=nums[pos1];nums[pos1]=tmp;}private void shiftdown(int[] nums,int pos){while(!isLeaf(nums,pos)){int left=pos*2+1;int right=pos*2+2;if(right<nums.length){left=nums[left]>nums[right]?left:right;}//是否需要调整堆if(nums[pos]>=nums[left]) return;swap(nums,pos,left);pos=left;}}public void buildHeap(int nums[]){for(int i=nums.length/2-1;i>=0;i--){shiftdown(nums,i);}}public void heapSort(int nums[]){for(int i=nums.length-1;i>=0;i--){swap(nums,0,i);shiftdown(nums,i);}}

总结

一、稳定性:

  • 稳定:冒泡排序、插入排序、归并排序和基数排序
  • 不稳定:选择排序、快速排序、希尔排序、堆排序

二、平均时间复杂度

  • O(n^2):直接插入排序,简单选择排序,冒泡排序。

  • 在数据规模较小时(9W内),直接插入排序,简单选择排序差不多。当数据较大时,冒泡排序算法的时间代价最高。性能为O(n^2)的算法基本上是相邻元素进行比较,基本上都是稳定的。

  • O(nlogn):快速排序,归并排序,希尔排序,堆排序。

其中,快排是最好的,其次是归并和希尔,堆排序在数据量很大时效果明显。

三、排序算法的选择

  1. 数据规模较小
  • (1)待排序列基本序的情况下,可以选择直接插入排序;

  • (2)对稳定性不作要求宜用简单选择排序,对稳定性有要求宜用插入或冒泡

  1. 数据规模不是很大
  • (1)完全可以用内存空间,序列杂乱无序,对稳定性没有要求,快速排序,此时要付出log(N)的额外空间。

  • (2)序列本身可能有序,对稳定性有要求,空间允许下,宜用归并排序

  1. 数据规模很大
  • (1)对稳定性有求,则可考虑归并排序。

  • (2)对稳定性没要求,宜用堆排序

  1. 序列初始基本有序(正序),宜用直接插入,冒泡

各算法复杂度如下:

数据结构和算法解析:排序问题简易总结相关推荐

  1. 数据结构与算法解析 -- “递归”篇

    2020-6-16 十步杀一人,千里不留行.事了拂衣去,深藏身与名. 李白 – <侠客行 > 一.概述 递归,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法.也就是说,递归算法 ...

  2. Java数据结构与算法解析(一)——表

    本节我们讨论常见常用的数据结构--表. 如果要通俗简单的说什么是表,那我们可以这样说:按顺序排好的元素集合就是表. 表的概述 抽象数据类型是带有一组操作的一些对象的结合 1.定义: 线性表是一个线性结 ...

  3. 殷人昆《数据结构与算法解析》目录(持续更新)

    绝对不删,纯属代码搬运.两年内,看能更新多少... 第一章 数据结构绪论 前六个跳过了,属于两个数比较大小难度题目.以后约定俗成,用c解决.c++慎用.确保它的基础性和实用性. 1-7 枚举数字排序问 ...

  4. Java数据结构与算法解析(二)——栈

    栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶.对栈的基本操作有push(进栈)和pop(出栈),对空栈进行push和pop,一般被认为栈ADT的一个错误.当push时空间用尽 ...

  5. 王争-算法与数据结构专栏第一期福利笔记(数据结构与算法学习书单)

    算法与数据结构书籍由浅入深: 闲暇拓展知识面: <算法帝国>:文科生也可以看懂 <数学之美> <算法之美> 入门书:(有感性认识) <算法图解>200页 ...

  6. 循环首次适应算法_数据结构与算法之2——排序问题

    排序真的是数据结构与算法中的重中之重啊,无论是对编程能力的提升,以后工作后的应用,或者是应对面试的时候都是经常需要用到的.基本的几个经典排序一定要做到滚瓜烂熟,能够做到给你一个具体的排序算法题,一定能 ...

  7. 数据结构》算法实现及解析].高一凡.

    未整理电子书4 [2012玛雅末日预言].(2012玛雅末日预言).布莱恩·达莫托.文字版.pdf: http://www.t00y.com/file/59485560 [21st.Century.C ...

  8. 数据结构精品电子书分享之《数据结构》算法实现及解析

    书籍简介 作者:高一凡 副书名:配合严蔚敏.吴伟民编著的<数据结构>(C语言版) 出版日期:2002-10-1 出版社:其它 页数:450 ISBN:7-5606-1176-1/TP*06 ...

  9. 阿里架构师强烈推荐《数据结构与算法经典问题解析》(PDF文档)

    前言: 小编整理了一份数据结构与算法经典问题解析核心知识点.覆盖递归和回溯.链表.栈.队列.树.优先队列和堆.队列.优先队列和堆.并查集ADT.排序.选择算法(中位数).散列.算法设计技术.分治算法. ...

最新文章

  1. Hubble.net 简介及与Lucene.net 对比测试
  2. Python 微信机器人:itchat库识别消息来源于群聊还是个人
  3. Oracle精简客户端配置
  4. Ubuntu 安装 Linux Deepin 截图工具(.deb)
  5. lua 函数回调技巧
  6. 性能指标之速率、带宽、吞吐量
  7. shell 死循环if判断_一个简单的shell脚本问题!怎么出现了死循环呢?谢谢
  8. 编程语言的通用概念[共同特征]
  9. 《数字图像处理 第三版》(冈萨雷斯)——第五章 图像复原与重建
  10. 第二章 让你的kali系统变得更好用
  11. android 动态仿磁贴,高仿 WIN8系统 磁贴点击下沉倾斜效果源码
  12. signature=a5d52dd3b1c2e95cc6ca952d8f8e8a05,6d53beb98227311df5d5a4ccf0177f23
  13. linux head
  14. 待支付取件费用是什么意思_待支付(待支付_订单待支付是什么意思_待支付取件费用)...
  15. Unity ParticleSystem 之 简单的电子自旋 Electrons ParticleSystem 粒子特效
  16. 《我的青春谁做主》剧中人物星座分析
  17. Android 5.0 调色 Palette调色功能
  18. AI测试与传统测试不同,需要考虑十个要点--新梦想软件测试
  19. SharpSCADA - 工控网关, 轻量级组态软件(笔记)
  20. postgresql 索引之 gin、btree_gin

热门文章

  1. python中的json
  2. [转]ToolTip在VC中的使用
  3. 3G,三足鼎立;花开千朵,各表一枝!!!
  4. VISUAL STUDIO 2019 快捷键
  5. 希腊字母常用指代意义及其中文读音
  6. rpm卸载mysql和php_CentOS 6.5 卸载mysql和php
  7. 为什么每次关机都要关闭mysql_在机器关机时关闭mysql服务实例
  8. diy手工制作泡沫小球_废物利用手工DIY教程。一次性筷子变废为宝,手工制作木屋模型...
  9. SQL性能--left join和inner join的运行速度与效率
  10. 索引的匹配方式有哪些?