数据结构和算法解析:排序问题简易总结
直接插入排序
直接插入排序(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);}}
选择排序
常用于取序列中最大最小的几个数时。
(如果每次比较都交换,那么就是交换排序;如果每次比较完一个循环再交换,就是简单选择排序。)遍历整个序列,将最小的数放在最前面。
遍历剩下的序列,将最小的数放在最前面。
重复第二步,直到只剩下一个数。
选择排序的时间复杂度为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;}}}}
快速排序
要求时间最快时。
- 选择第一个数为p,小于p的数放在左边,大于p的数放在右边。
- 递归的将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);}
归并排序
速度仅次于快速排序,内存少的时候使用,可以进行并行计算的时候使用。
- 选择相邻两个数组成一个有序序列。
- 选择相邻的两个有序序列组成一个有序序列。重复第二步,直到全部组成一个有序序列。
归并排序,是一种稳定的排序是算法这个算法的时间复复杂度都是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];}}
堆排序
对简单选择排序的优化。
- 将序列构建成大顶堆。
- 将根节点与最后一个节点交换,然后断开最后一个节点。
- 重复第一、二步,直到所有节点断开。
//堆排序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)待排序列基本序的情况下,可以选择直接插入排序;
(2)对稳定性不作要求宜用简单选择排序,对稳定性有要求宜用插入或冒泡
- 数据规模不是很大
(1)完全可以用内存空间,序列杂乱无序,对稳定性没有要求,快速排序,此时要付出log(N)的额外空间。
(2)序列本身可能有序,对稳定性有要求,空间允许下,宜用归并排序
- 数据规模很大
(1)对稳定性有求,则可考虑归并排序。
(2)对稳定性没要求,宜用堆排序
- 序列初始基本有序(正序),宜用直接插入,冒泡
各算法复杂度如下:
数据结构和算法解析:排序问题简易总结相关推荐
- 数据结构与算法解析 -- “递归”篇
2020-6-16 十步杀一人,千里不留行.事了拂衣去,深藏身与名. 李白 – <侠客行 > 一.概述 递归,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法.也就是说,递归算法 ...
- Java数据结构与算法解析(一)——表
本节我们讨论常见常用的数据结构--表. 如果要通俗简单的说什么是表,那我们可以这样说:按顺序排好的元素集合就是表. 表的概述 抽象数据类型是带有一组操作的一些对象的结合 1.定义: 线性表是一个线性结 ...
- 殷人昆《数据结构与算法解析》目录(持续更新)
绝对不删,纯属代码搬运.两年内,看能更新多少... 第一章 数据结构绪论 前六个跳过了,属于两个数比较大小难度题目.以后约定俗成,用c解决.c++慎用.确保它的基础性和实用性. 1-7 枚举数字排序问 ...
- Java数据结构与算法解析(二)——栈
栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶.对栈的基本操作有push(进栈)和pop(出栈),对空栈进行push和pop,一般被认为栈ADT的一个错误.当push时空间用尽 ...
- 王争-算法与数据结构专栏第一期福利笔记(数据结构与算法学习书单)
算法与数据结构书籍由浅入深: 闲暇拓展知识面: <算法帝国>:文科生也可以看懂 <数学之美> <算法之美> 入门书:(有感性认识) <算法图解>200页 ...
- 循环首次适应算法_数据结构与算法之2——排序问题
排序真的是数据结构与算法中的重中之重啊,无论是对编程能力的提升,以后工作后的应用,或者是应对面试的时候都是经常需要用到的.基本的几个经典排序一定要做到滚瓜烂熟,能够做到给你一个具体的排序算法题,一定能 ...
- 数据结构》算法实现及解析].高一凡.
未整理电子书4 [2012玛雅末日预言].(2012玛雅末日预言).布莱恩·达莫托.文字版.pdf: http://www.t00y.com/file/59485560 [21st.Century.C ...
- 数据结构精品电子书分享之《数据结构》算法实现及解析
书籍简介 作者:高一凡 副书名:配合严蔚敏.吴伟民编著的<数据结构>(C语言版) 出版日期:2002-10-1 出版社:其它 页数:450 ISBN:7-5606-1176-1/TP*06 ...
- 阿里架构师强烈推荐《数据结构与算法经典问题解析》(PDF文档)
前言: 小编整理了一份数据结构与算法经典问题解析核心知识点.覆盖递归和回溯.链表.栈.队列.树.优先队列和堆.队列.优先队列和堆.并查集ADT.排序.选择算法(中位数).散列.算法设计技术.分治算法. ...
最新文章
- Hubble.net 简介及与Lucene.net 对比测试
- Python 微信机器人:itchat库识别消息来源于群聊还是个人
- Oracle精简客户端配置
- Ubuntu 安装 Linux Deepin 截图工具(.deb)
- lua 函数回调技巧
- 性能指标之速率、带宽、吞吐量
- shell 死循环if判断_一个简单的shell脚本问题!怎么出现了死循环呢?谢谢
- 编程语言的通用概念[共同特征]
- 《数字图像处理 第三版》(冈萨雷斯)——第五章 图像复原与重建
- 第二章 让你的kali系统变得更好用
- android 动态仿磁贴,高仿 WIN8系统 磁贴点击下沉倾斜效果源码
- signature=a5d52dd3b1c2e95cc6ca952d8f8e8a05,6d53beb98227311df5d5a4ccf0177f23
- linux head
- 待支付取件费用是什么意思_待支付(待支付_订单待支付是什么意思_待支付取件费用)...
- Unity ParticleSystem 之 简单的电子自旋 Electrons ParticleSystem 粒子特效
- 《我的青春谁做主》剧中人物星座分析
- Android 5.0 调色 Palette调色功能
- AI测试与传统测试不同,需要考虑十个要点--新梦想软件测试
- SharpSCADA - 工控网关, 轻量级组态软件(笔记)
- postgresql 索引之 gin、btree_gin
热门文章
- python中的json
- [转]ToolTip在VC中的使用
- 3G,三足鼎立;花开千朵,各表一枝!!!
- VISUAL STUDIO 2019 快捷键
- 希腊字母常用指代意义及其中文读音
- rpm卸载mysql和php_CentOS 6.5 卸载mysql和php
- 为什么每次关机都要关闭mysql_在机器关机时关闭mysql服务实例
- diy手工制作泡沫小球_废物利用手工DIY教程。一次性筷子变废为宝,手工制作木屋模型...
- SQL性能--left join和inner join的运行速度与效率
- 索引的匹配方式有哪些?