常见的8种排序算法

部分转自互联网......

下面要讲到的8种排序都属于内部排序,既在内存中完成,主要从理论原理方面来分析的。

   插入排序

①直接插入排序

例:六个数12 15 9 20  6 31 24 用直接插入排序,如下图:

思路:

第一步:从给出的六个数中,随便拿出一个数,比如12,形成一个有序的数据序列(一个数当然是有序的数据序列了,不看12之外的数,就当其他的数不存在);

第二步:从剩下的五个数中挑出一个数来,比如15,和刚才的12作比较,12<15,因此,放在12后面,形成数据序列12 15;

第三步:从剩下的四个数中挑出一个数来,比如9,和刚才的有序数据序列12 15作比较,9 < 12 < 15,因此,放在最前面,形成数据序列9 12 15;

第N步,经过这样一个一个的插入并对比,就形成了上图所示的排序结果。在一个元素插入时,首先要和数据序列中最大的元素作比较,如果遇到相同的,则放在相同元素的后面。

特性:

因为要不断的插入,因此直接插入排序一般采用链表结构,属于稳定排序。

②希尔(Shell)排序

是直接插入排序的改进,例:十个数57 68 59 52 72 28 96 33 24 19用希尔排序,如下图:

思路:

第一步:用排序数字的总数除以2,取奇数得到步长(增量)d1 = 5;

第二步:根据步长d1,将十个数分成五组,如图所示,对这五组各自进行直接插入排序;

第三步:用步长d2继续除以2,取最近的奇数得到步长d2=3;

第四步:根据步长d2,将十个数分成三组,如图所示,对着五组各自进行直接插入排序;

第N步:重复上述分组和排序操作,直到步长变成1,即所有记录放进一个组中排序为止。

特性

由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

   选择排序

①简单选择排序

例:四个数57 68 59 52选择排序:

思路:

第一步:从四个数找到最小的,和初始状态排在第一位的移动互换;

第二步:从剩下三个数中找到最小的,和初始状态排在第二位的移动互换;

第N步:重复上述查找最小和互换的步骤,直到最后一个为止。

特性

举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中两个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

②堆排序(图片示例均来自quanquanfly

如果不清楚堆及特性可移步本人上一篇博客《常用数据结构-几种特殊的二叉树》,关于堆排序,有些复杂,下面举例说明:例:对数列{12,56,23,26,15,86,92,75,65}建立大顶堆(大根堆),则初始堆是?

思路:

分为两个大的过程,第一是建堆过程;

思路:

第一步:根据完全二叉树排列给出的数字,如上图中第一个图;

第二步:因为树是一个单向的过程,叶子结点是无法知道父结点的,因此不能拿叶子结点去和父结点比较;根据结点i,i>=n/2为叶子结点的特性,找出最后一个非叶子结点,然后拿它和它的叶子结点作比较,如果比叶子结点小,则互换(建立的是大顶堆),反之不动。

第三步:紧接着调整n/2 - 1号结点(求出n/2 -1 = 3,也就是23号结点),从图中看出23号结点的两个结点都比它大,那么择优选取一个最大的进行互换。

第N步:按照上述方法,依次互换,最后建立了一个大顶堆。

第二是堆排序过程:

思路:

第一步:首先根据上面建立好的初始堆将根结点92输出,然后用编号最大的结点65替代根结点,断开最大编号结点的指针。

第二步:上一步完成后,检查65结点是否符合大顶堆要求,如果不符合又进行一次建堆的过程(参照第一个过程)。

第N步:按照上述两个步骤,反复操作,就会得到需要的结果。

有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法

   交换排序

①冒泡排序

比较常见的排序算法。举例说明:

思路:

第一步:将倒数第一个和倒数第二个数进行比较,如果小,则互换;

第二步:将倒数第二个和倒数第三个数进行比较,如果小,则互换;

第N步:筛选出最小的一个数,然后从剩下的数中按照上面的方法反复操作,得到需要的序列。

特性

如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

②快速排序

快速排序(分治思想)是对冒泡排序的一种改进,思想:从数列中挑出一个元素,称为 "基准"(pivot);重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割结束之后,该基准就处于数列的中间位置。这个称为分割(partition)操作;递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

思路:

第一步:从给出的数列中找到一个基准,如图中的57,左指针指向57,右指针指向最后一个元素;

第二步:对左指针与右指针指向的元素作对比,右指针指向的元素19比左指针指向的元素57小(基准),互换位置;

第三步:左指针右移一个后跟右指针对比,68>57,因此互换;

第N步:按照上述的步骤经过指针的不断移动和元素的对比互换,最后得出第一个以57为中心的序列(左侧小于57,右侧大于57);接下来利用递归分别对57前后的进行排序。

特性

上面右侧的动态图很好的说明了快速排序的思路,快速排序是一个不稳定的排序算法。

   归并排序

该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

思路:

第一步:把待排序的每一个元素看做一个有序表(则由n个有序表),通过两两合并,生成?n/2?个长度为2(最后一个表的长度可能小于2)的有序表。

第二步:每组内部进行排序;

第三步:两组两组进行归并,将两个指针分别定为两组最小的两个数,然后进行比较,小的挑出来,指针后移,继续比较。

第N步:进过上述不断的归并和比较,最终得出一个正确的序列。

归并排序是稳定的排序算法

   基数排序

基数排序其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。

思路:

第一步:将给出的序列元素的个位进行收集,然后按照如图所示,放到对应的位置(0-9序列),并根据个位排出大小,形成了一个序列。

第二步:收集十位,根据第一步产生的序列放到对应的位置,形成一个新的序列;

第三步:收集百位,根据第二步产生的序列放到对应的位置,形成想要的结果序列。

特性

基数排序基于分别排序,分别收集,所以其是稳定的排序算法

   各类算法的比较

时间: 2024-10-10 13:26:14

常见的8种排序算法的相关文章

Java常见的几种排序算法-插入、选择、冒泡、快排、堆排等

本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排序.快速排序(重点).堆排序.归并排序等等.看下图: 给定数组:int data[] = {9,2,7,19,100,97,63,208,55,78} 一.直接插入排序(内部排序.O(n2).稳定) 原理:从待排序的数中选出一个来,插入到前面的合适位置. [java] view plain copy

常见的几种排序算法-插入、选择、冒泡、快排、堆排等

排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排序.快速排序(重点).堆排序.归并排序等等.看下图: 给定数组:int data[] = {9,2,7,19,100,97,63,208,55,78} 一.直接插入排序(内部排序.O(n2).稳定) 原理:从待排序的数中选出一个来,插入到前面的合适位置. package com.xtfggef.algo.sort; public

常见的几种排序算法

1 #include <stdio.h> 2 3 //直接插入排序算法 4 void InsertSort(int a[], int size) 5 { 6 int i, j; 7 int key; //待插入的值 8 for (j = 1; j < size; j++) 9 { 10 key = a[j]; 11 i = j - 1; 12 while (i >= 0 && a[i]>key) 13 { 14 a[i + 1] = a[i]; 15 i--;

博客一,常见的几种排序算法的Java实现

一.插入排序 算法导论上有很形象的比喻,把插入排序类比成扑克牌,默认你手里本身拥有的第一张是有序的,第二章和第一张对比后决定其位置,以此类推.代码如下: 1 public class InsertSort { 2 public void insertSort(int[] a){ 3 if(a==null||a.length==0||a.length==1){ 4 return ; 5 } 6 //i代表已有序的数组元素的边界, 7 for(int i = 0 ; i<a.length-1 ;i+

PHP常见的几种排序算法

一.冒泡排序 排序原理:对一组数据,比较相邻数据的大小,把小的数据放在前面,值大的放在后面(升序排序) 举例说明: $arr = [6, 3, 8, 2, 9, 1]; 第一轮排序: 第一次比较 6和3比较: 3    6   8   2   9   1 第二次比较 6和8比较: 3    6   8   2   9   1 第三次比较 8和2比较: 3    6   2   8   9   1 第四次比较 8和9比较: 3    6   2   8   9   1 第五次比较 9和1比较: 3

整理的8种排序算法的总结和比较

1 快速排序(QuickSort) 快速排序是一个就地排序,分而治之,大规模递归的算法.从本质上来说,它是归并排序的就地版本.快速排序可以由下面四步组成. (1) 如果不多于1个数据,直接返回. (2) 一般选择序列最左边的值作为支点数据. (3) 将序列分成2部分,一部分都大于支点数据,另外一部分都小于支点数据. (4) 对两边利用递归排序数列. 快速排序比大部分排序算法都要快.尽管我们可以在某些特殊的情况下写出比快速排序快的算法,但是就通常情况而言,没有比它更快的了.快速排序是递归的,对于内

常见的五类排序算法图解和实现(多关键字排序:基数排序以及各个排序算法的总结)

基数排序思想 完全不同于以前的排序算法,可以说,基数排序也叫做多关键字排序,基数排序是一种借助“多关键字排序”的思想来实现“单关键字排序”的内部排序算法. 两种方式: 1.最高位优先,先按照最高位排成若干子序列,再对子序列按照次高位排序 2.最低位优先:不必分子序列,每次排序全体元素都参与,不比较,而是通过分配+收集的方式. 多关键字排序 例:将下表所示的学生成绩单按数学成绩的等级由高到低排序,数学成绩相同的学生再按英语成绩的高低等级排序.        第一个关键字是数学成绩,第二个关键字是英

总结N种排序算法及实现

排序算法是一个简单的问题,但在此问题上却有大量的研究!当前的排序算法通常按照如下四个方面进行分类(或是评价): 1.时间复杂度:一个排序算法的理想性能是O(n).一般而言,好的性能O(nlogn),坏的性能O(n2). 2.空间复杂度(内存使用量) 3.稳定性:稳定的排序算法会让原本有相等键值的记录维持原本的相对次序. 4.排序方式:插入.交换.选择.合并等 一.冒泡排序:这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端. 步骤:1.比较相邻的两个元素,如果第一个比第二个大,就

12种排序算法:原理、图解、动画视频演示、代码以及笔试面试题目中的应用

出处:http://blog.csdn.net/han_xiaoyang/article/details/12163251. 声明:版权所有,转载请注明出处,谢谢. 0.前言 从这一部分开始直接切入我们计算机互联网笔试面试中的重头戏算法了,初始的想法是找一条主线,比如数据结构或者解题思路方法,将博主见过做过整理过的算法题逐个分析一遍(博主当年自己学算法就是用这种比较笨的刷题学的,囧),不过又想了想,算法这东西,博主自己学的过程中一直深感,基础还是非常重要的,很多难题是基础类数据结构和题目的思想综