常见的八种经典排序方法
十大经典排序算法总结
⼗⼤经典排序算法总结最近⼏天在研究算法,将⼏种排序算法整理了⼀下,便于对这些排序算法进⾏⽐较,若有错误的地⽅,还请⼤家指正0、排序算法说明0.1 排序术语稳定:如果a=b,且a原本排在b前⾯,排序之后a仍排在b的前⾯不稳定:如果a=b,且a原本排在b前⾯,排序之后排在b的后⾯时间复杂度:⼀个算法执⾏所耗费的时间空间复杂度:⼀个算法执⾏完所需内存的⼤⼩内排序:所有排序操作都在内存中完成外排序:由于数据太⼤,因此把数据放在磁盘中,⽽排序通过磁盘和内存的数据传输才能进⾏0.2算法时间复杂度、空间复杂度⽐较0.3名词解释n:数据规模k:桶的个数In-place:占⽤常数内存,不占⽤额外内存Out-place:占⽤额外内存0.4算法分类1.冒泡排序冒泡排序是⼀种简单的排序算法。
它重复地⾛访过要排序的数列,⼀次⽐较两个元素,如果它们的顺序错误就把它们交换过来。
⾛访数列的⼯作是重复地进⾏直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越⼩的元素会经由交换慢慢“浮”到数列的顶端1.1算法描述⽐较相邻的元素,如果前⼀个⽐后⼀个打,就交换对每⼀对相邻元素做同样的⼯作,从开始第⼀对到结尾最后⼀对,这样在最后的元素应该会是最⼤的数针对所有的元素重复以上的步骤,除了最后⼀个重复步骤1-3,知道排序完成1.2动图演⽰1.3代码实现public static int[] bubbleSort(int[] array) {if (array.length == 0)return array;for (int i = 0; i < array.length; i++)for (int j = 0; j < array.length - 1 - i; j++)if (array[j + 1] < array[j]) {int temp = array[j + 1];array[j + 1] = array[j];array[j] = temp;}return array;}1.4算法分析最佳情况:T(n) = O(n) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(n2)2.选择排序表现简单直观的最稳定的排序算法之⼀,因为⽆论什么数据都是O(n2)的时间复杂度,⾸先在未排序序列中找到最⼩(⼤)元素,与数组中第⼀个元素交换位置,作为排序序列的起始位置,然后再从剩余未排序元素中继续寻找最⼩(⼤)的元素,与数组中的下⼀个元素交换位置,也就是放在已排序序列的末尾2.1算法描述1.初始状态:⽆序区为R[1..n],有序区为空2.第i躺排序开始时,当前有序区和⽆序区R[1..i-1]、R[i..n]3.n-1趟结束,数组有序化2.2动图演⽰2.3代码实现public static int[] selectionSort(int[] array) {if (array.length == 0)return array;for (int i = 0; i < array.length; i++) {int minIndex = i;for (int j = i; j < array.length; j++) {if (array[j] < array[minIndex]) //找到最⼩的数minIndex = j; //将最⼩数的索引保存}int temp = array[minIndex];array[minIndex] = array[i];array[i] = temp;}return array;}2.4算法分析最佳情况:T(n) = O(n2) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(n2)3、插⼊排序是⼀种简单直观的排序算法,通过构建有序序列,对于未排序序列,在已排序序列中从后向前扫描,找到相应位置并插⼊,需要反复把已排序元素逐步向后挪位,为最新元素腾出插⼊空间3.1算法描述1.从第⼀个元素开始,该元素可以认为已经被排序2.取出下⼀个元素(h),在已排序的元素序列中从后往前扫描3.如果当前元素⼤于h,将当前元素移到下⼀位置4.重复步骤3,直到找到已排序的元素⼩于等于h的位置5.将h插⼊到该位置6.重复步骤2-53.2动图演⽰3.3代码实现public static int[] insertionSort(int[] array) {if (array.length == 0)return array;int current;for (int i = 0; i < array.length - 1; i++) {current = array[i + 1];int preIndex = i;while (preIndex >= 0 && current < array[preIndex]) {array[preIndex + 1] = array[preIndex];preIndex--;}array[preIndex + 1] = current;}return array;}3.4算法分析最佳情况:T(n) = O(n) 最坏情况:T(n) = O(n2) 平均情况:T(n) = O(n2)4、希尔排序是简单插⼊排序经过改进之后的⼀个更⾼效的版本,也称为缩⼩增量排序,同时该算法是冲破O(n2)的第⼀批算法之⼀。
浅析八大排序的方法有哪些
浅析八大排序的方法有哪些
八大排序方法有以下几种:
1. 冒泡排序(Bubble Sort):重复比较相邻的两个元素,查看是否需要交换,每次将最大(或最小)的元素“冒泡”到顶部(或底部)。
2. 选择排序(Selection Sort):每次从待排序的数据中选出最小(或最大)的元素,放置到已排序位置的最后,直到所有元素排序完成。
3. 插入排序(Insertion Sort):将待排序数据分为已排序和未排序两部分,每次将未排序中第一个元素插入到已排序的合适位置。
4. 希尔排序(Shell Sort):是插入排序的一种改进,先将数据按照一定的步长进行分组,对每组进行插入排序,再逐渐缩小步长,最终步长为1,完成排序。
5. 归并排序(Merge Sort):将待排序的数据递归地分割成较小的子序列,然后再将子序列归并排序,最终得到有序的结果。
6. 快速排序(Quick Sort):选取基准值(一般为待排序数据的第一个元素),将数据分割成两部分,在基准值左边的数据都小于基准值,在右边的数据都大于基准值,然后对左右两部分数据递归地进行快速排序。
7. 堆排序(Heap Sort):将待排序数据构建成一个大(或小)根堆,将堆顶的元素与末尾元素交换,然后对剩余未排序部分进行堆调整,继续交换堆顶与末尾元素,重复上述步骤,直到完成排序。
8. 计数排序(Counting Sort):对于给定的输入序列中的每个元素x,确定小于x的元素个数。
利用这一信息,可以直接确定x在输出序列中的位置,最后按照确定的位置输出元素,即得到有序序列。
以上就是八大排序方法的简要介绍。
不同的排序算法具有不同的时间复杂度和适用场景,具体选择哪种排序算法应根据实际情况进行评估和选择。
各种排序方法总结
选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
冒泡法:这是最原始,也是众所周知的最慢的算法了。
他的名字的由来因为它的工作看来象是冒泡:复杂度为O(n*n)。
当数据为正序,将不会有交换。
复杂度为O(0)。
直接插入排序:O(n*n)选择排序:O(n*n)快速排序:平均时间复杂度log2(n)*n,所有内部排序方法中最高好的,大多数情况下总是最好的。
归并排序:l og2(n)*n堆排序:l og2(n)*n希尔排序:算法的复杂度为n的1.2次幂这里我没有给出行为的分析,因为这个很简单,我们直接来分析算法:首先我们考虑最理想的情况1.数组的大小是2的幂,这样分下去始终可以被2整除。
假设为2的k次方,即k=log2(n)。
2.每次我们选择的值刚好是中间值,这样,数组才可以被等分。
第一层递归,循环n次,第二层循环2*(n/2)......所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n所以算法复杂度为O(lo g2(n)*n) 其他的情况只会比这种情况差,最差的情况是每次选择到的midd le都是最小值或最大值,那么他将变成交换法(由于使用了递归,情况更糟)。
但是你认为这种情况发生的几率有多大??呵呵,你完全不必担心这个问题。
实践证明,大多数的情况,快速排序总是最好的。
如果你担心这个问题,你可以使用堆排序,这是一种稳定的O(log2(n)*n)算法,但是通常情况下速度要慢于快速排序(因为要重组堆)。
最简单的排序
最简单的排序排序是一种常见的操作,可以将一组元素按照一定的规则重新排列,使其达到某种有序的状态。
排序在生活中随处可见,比如我们买菜时,需要将菜按照大小、种类进行整理;在图书馆,图书也是按照编号或者分类进行排序的。
下面我们来介绍几种最简单的排序算法。
1. 冒泡排序冒泡排序是一种简单直观的排序算法,它重复地遍历要排序的元素,比较相邻的两个元素,如果它们的顺序错误就交换位置,直到没有需要交换的元素为止。
这样最大(或最小)的元素就会像气泡一样逐渐升(或降)到最后的位置。
2. 选择排序选择排序是一种简单直观的排序算法,它的工作原理如下:首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小(或最大)元素,放到已排序序列的末尾。
以此类推,直到所有元素均排序完毕。
3. 插入排序插入排序是一种简单直观的排序算法,它的工作原理如下:将数组分成已排序部分和未排序部分,初始时已排序部分只有一个元素,然后将未排序部分的元素逐个插入到已排序部分的合适位置,直到所有元素都被插入到已排序部分为止。
4. 快速排序快速排序是一种高效的排序算法,它的工作原理如下:选择一个基准元素,将大于基准元素的元素放到右边,小于基准元素的元素放到左边,然后再对左右两个子序列分别进行快速排序,直到整个序列有序。
以上是几种最简单的排序算法,它们都有各自的特点和适用场景。
在实际应用中,我们可以根据问题的具体需求选择合适的排序算法。
排序算法的效率也是我们需要考虑的一个重要因素,通常来说,快速排序是效率最高的排序算法之一。
排序是一种常见的操作,可以帮助我们将一组元素按照一定的规则重新排列,使其达到某种有序的状态。
冒泡排序、选择排序、插入排序和快速排序是几种最简单的排序算法,它们都有各自的特点和适用场景。
在实际应用中,我们可以根据问题的具体需求选择合适的排序算法,以提高效率和准确性。
通过学习和掌握这些排序算法,我们可以更好地理解和应用排序的原理和方法。
排序算法十大经典方法
排序算法十大经典方法
排序算法是计算机科学中的经典问题之一,它们用于将一组元素按照一定规则排序。
以下是十大经典排序算法:
1. 冒泡排序:比较相邻元素并交换,每一轮将最大的元素移动到最后。
2. 选择排序:每一轮选出未排序部分中最小的元素,并将其放在已排序部分的末尾。
3. 插入排序:将未排序部分的第一个元素插入到已排序部分的合适位置。
4. 希尔排序:改进的插入排序,将数据分组排序,最终合并排序。
5. 归并排序:将序列拆分成子序列,分别排序后合并,递归完成。
6. 快速排序:选定一个基准值,将小于基准值的元素放在左边,大于基准值的元素放在右边,递归排序。
7. 堆排序:将序列构建成一个堆,然后一次将堆顶元素取出并调整堆。
8. 计数排序:统计每个元素出现的次数,再按照元素大小输出。
9. 桶排序:将数据分到一个或多个桶中,对每个桶进行排序,最后输出。
10. 基数排序:按照元素的位数从低到高进行排序,每次排序只考虑一位。
以上是十大经典排序算法,每个算法都有其优缺点和适用场景,选择合适的算法可以提高排序效率。
【十大经典排序算法(动图演示)】 必学十大经典排序算法
【十大经典排序算法(动图演示)】必学十大经典排序算法0.1 算法分类十种常见排序算法可以分为两大类:比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
0.2 算法复杂度0.3 相关概念稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后a 可能会出现在b 的后面。
时间复杂度:对排序数据的总的操作次数。
反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
1、冒泡排序(Bubble Sort)冒泡排序是一种简单的排序算法。
它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
1.1 算法描述比较相邻的元素。
如果第一个比第二个大,就交换它们两个;对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;针对所有的元素重复以上的步骤,除了最后一个;重复步骤1~3,直到排序完成。
1.2 动图演示1.3 代码实现1.unction bubbleSort(arr) {2. varlen = arr.length;3. for(vari = 0; i arr[j+1]) {// 相邻元素两两对比6. vartemp = arr[j+1];// 元素交换7. arr[j+1] = arr[j];8. arr[j] = temp;9. }10. }11. }12. returnarr;13.}2、选择排序(Selection Sort)选择排序(Selection-sort)是一种简单直观的排序算法。
经典十大排序算法
经典⼗⼤排序算法前⾔排序种类繁多,⼤致可以分为两⼤类:⽐较类排序:属于⾮线性时间排序,时间复杂度不能突破下界O(nlogn);⾮⽐较类排序:能达到线性时间O(n),不是通过⽐较来排序,有基数排序、计数排序、桶排序。
了解⼀个概念:排序的稳定性稳定是指相同⼤⼩的元素多次排序能保证其先后顺序保持不变。
假设有⼀些学⽣的信息,我们先根据他们的姓名进⾏排序,然后我们还想根据班级再进⾏排序,如果这时使⽤的时不稳定的排序算法,那么第⼀次的排序结果可能会被打乱,这样的场景需要使⽤稳定的算法。
堆排序、快速排序、希尔排序、选择排序是不稳定的排序算法,⽽冒泡排序、插⼊排序、归并排序、基数排序是稳定的排序算法。
1、冒泡排序⼤多数⼈学编程接触的第⼀种排序,名称很形象。
每次遍历排出⼀个最⼤的元素,将⼀个最⼤的⽓泡冒出⽔⾯。
时间复杂度:平均:O(n2);最好:O(n);最坏:O(n2)空间复杂度:O(1)public static void bubbleSort(int[] arr) {/*** 总共⾛len-1趟即可,每趟排出⼀个最⼤值放在最后*/for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - i - 1; j++) {if (arr[j] > arr[j + 1]) {int tp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tp;}}}}2、选择排序最直观易理解的排序算法,每次排出⼀个最⼩的元素。
也是最稳定的算法,时间复杂度稳定为O(n^2)。
需要⼀个变量记录每次遍历最⼩元素的位置。
时间复杂度:O(n2)空间复杂度:O(1)public static void selectSort(int[] arr){int n = arr.length;for (int i = 0; i < n; i++) {int maxIdx = 0;for(int j = 1; j < n - i; j++){if(arr[maxIdx] < arr[j]){maxIdx = j;}}int tp = arr[maxIdx];arr[maxIdx] = arr[n - 1 - i];arr[n - 1 - i] = tp;}}3、插⼊排序⼀种直观的排序算法,从第⼆个元素开始,每次往前⾯遍历找到⾃⼰该在的位置。
排序方法有哪些
排序方法有哪些在日常生活和工作中,我们经常需要对一些事物或者数据进行排序。
排序是将一组数据按照一定的规则进行排列的过程,它可以帮助我们更清晰地了解事物之间的关系,找到最合适的解决方案。
在实际操作中,有许多不同的排序方法可以使用,每种方法都有其特点和适用场景。
下面将介绍一些常见的排序方法。
1. 冒泡排序。
冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
重复这个过程直到整个数列有序。
冒泡排序的时间复杂度为O(n^2),在数据量较小的情况下比较实用。
2. 选择排序。
选择排序是一种简单直观的排序算法,它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
选择排序的时间复杂度也为O(n^2),但由于不涉及交换操作,所以相对于冒泡排序来说性能上会更好一些。
3. 插入排序。
插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
插入排序的时间复杂度也为O(n^2),但是在实际应用中,当数据规模较小时,插入排序会比选择排序和冒泡排序更加高效。
4. 快速排序。
快速排序是一种分治的排序算法,它的基本思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快速排序的时间复杂度为O(nlogn),在大多数情况下都比前面介绍的排序方法要快。
5. 归并排序。
归并排序是一种稳定的排序算法,它的基本思想是将两个有序的子序列合并成一个有序序列。
归并排序的时间复杂度也为O(nlogn),并且由于其稳定性和适用于大规模数据的特点,因此在实际应用中得到了广泛的应用。
6. 堆排序。
堆排序是一种树形选择排序,它的基本思想是利用堆这种数据结构来进行排序。
八大排序总结
1.冒泡排序(稳定排序)思想:从第一个开始,每两个数进行比较,将较大(较小)的数交换到前面直到最后一个数。
两层循环嵌套,内层用于遍历一次数组,每次两两比较,外层控制遍历的次数。
时间复杂度:O(n^2).空间复杂度:O(1)。
2.直接插入排序(稳定排序)思想:每次把一个待排的数记录下来,按其值的大小插入前面适当的位置,知道全部插完为止。
时间复杂度:O(n^2)。
空间复杂度:O(1)。
3.选择排序(不稳定排序)思想:两层for循环嵌套,内层用于每次从(j=i+1)的位置开始,将最大(最下)的数找出来,和i位置的值交换,i++,外层控制找最大值的次数。
时间复杂度:O(n^2)。
空间复杂度:O(1)。
4.希尔排序(不稳定排序)思想:他是一种分组插入排序的方法,对于分的组数应该互为素数。
每次将下标间距相等的数分为一组,对每组进行插入排序,直到组数变成一为止,最后对整个数组进行一次排序。
时间复杂度:O(n^1.3)。
空间复杂度:O(1)。
5.堆排序(不稳定排序)思想:堆排序利用堆积树进行选择排序。
堆是二叉树,当由小到大排序时,建立大根堆,首先对树进行调整(从最后一棵枝桠开始),调整后的最大值便存储在0节点,将0节点的值与最后一个节点的值交换,便找出了整个数组的最大值,用for循环对整个树在进行调整,依次得到较大的值,知道数组有序。
时间复杂度:O(nlog2n)。
空间复杂度:O(1)。
6.快速排序(不稳定排序)思想:快排是对冒泡排序的一种改进。
每次将第一个数作为基准,一趟排序后,数组要分成两部分,比基准小的都放在左边,大的放在右边,因此需要定义low,high分别指向每块的第一个数和最后一个数。
通过对基准左边和右边数的个数的判断,分别对左右两边进行找基准排序,对此,既可以使用递归进行后面的排序,也可用while循环进行。
优化一:每次用rand()函数随机产生high指向的值。
rand()%(end-start)+start.产生从0到(end-start)+start.的随机数优化二:三数取中法。
排序的几种方法范文
排序的几种方法范文排序是计算机科学中的一个基本概念,常用于将数据按照一定的规则进行排列。
排序算法根据其具体实现和时间复杂度的不同,可以分为多种方法。
下面将介绍常见的几种排序方法及其特点:1. 冒泡排序(Bubble Sort):冒泡排序是最简单的排序算法之一,它的基本思想是通过不断比较相邻的元素,将较大的元素向后移动,直到整个序列有序。
具体实现过程中,通过多次遍历序列,每次比较相邻元素并交换位置,直到最终有序。
冒泡排序的时间复杂度为O(n^2),其中n是待排序序列的长度。
因此,当待排序序列较大时,冒泡排序的效率较低。
2. 选择排序(Selection Sort):选择排序是一种简单但低效的排序算法。
它的基本思想是每次通过选择最小(或最大)的元素,并将其放置在已排序序列的末尾。
具体实现过程中,遍历待排序序列,每次选择最小(或最大)的元素,并与当前位置交换,直到整个序列有序。
选择排序的时间复杂度为O(n^2),其中n是待排序序列的长度。
与冒泡排序相比,选择排序的交换次数较少,因此理论上比冒泡排序要稍快一些。
3. 插入排序(Insertion Sort):插入排序是一种简单且常用的排序算法。
它的基本思想是将待排序序列分为已排序和未排序两部分,每次从未排序序列中选择一个元素,并插入到已排序序列中的适当位置。
具体实现过程中,通过将待排序元素与已排序部分从后往前进行比较,并将较大的元素后移,直到找到合适的位置插入。
插入排序的时间复杂度为O(n^2),其中n是待排序序列的长度。
在待排序序列基本有序的情况下,插入排序的效率较高,因为此时每次插入元素的比较次数较少。
4. 快速排序(Quick Sort):快速排序是一种高效的排序算法,它利用了分治的思想。
它的基本思想是选择一个基准元素,将比基准元素小的元素放在左边,比基准元素大的元素放在右边,然后分别对左右两部分进行递归排序。
具体实现过程中,通过不断选择基准元素和分割序列,并进行递归排序,直到整个序列有序。
八大排序详解
八大排序详解八大排序算法包括插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序和基数排序。
1. 插入排序:这是一种简单直观的排序算法,其工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
在插入过程中,如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面,因此插入排序是稳定的。
2. 希尔排序:也称递减增量排序算法,是插入排序的一种更高效的改进版本。
3. 选择排序:它的工作原理是首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。
以此类推,直到所有元素均排序完毕。
4. 冒泡排序:这种排序算法会重复地遍历待排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
5. 归并排序:归并排序是一种采用分治法的排序算法。
它将待排序的序列分成若干个子序列,每个子序列单独进行排序,然后将已排序的子序列进行合并,得到最终的排序结果。
6. 快速排序:快速排序采用分治法进行排序。
在每一步中,它选择一个“基准”元素,并将数组分为两部分,其中一部分的所有元素都比基准元素小,另一部分的所有元素都比基准元素大。
然后,对这两部分独立地进行快速排序。
7. 堆排序:堆排序是一种树形选择排序,是对直接选择排序的有效改进。
堆是一种特殊的树形数据结构,它的每个父节点都大于或等于(小于或等于)其子节点(通常称为大顶堆或小顶堆)。
8. 基数排序:基数排序是一种非比较整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。
以上就是八大排序算法的详解,这些算法各有特点和使用场景,可以根据实际情况选择合适的算法。
八大排序方法
1、选择排序:每次排序都把最小的放在最前面,或者把最大的放到最前面private function selectionSort(array:Array):void{var len:int = array.length;for (var i:int = 0; i < len - 1; i++){var min:int = array[i];var minIndex:int = i;for (var k:int = i + 1; k < len; k++){if (array[k] < min){min = array[k];minIndex = k;}}if (minIndex != i){array[minIndex] = array[i];array[i] = min;}}}2、冒泡排序:依次交换,每次排序之后最大的数都到了最后private function bubbleSort(array:Array):void{var len:int = array.length;var needSort:Boolean = true;for (var i:int = 1; i < len && needSort; i++){needSort = false;for (var k:int = 0; k < len - i; k++){if (array[k] > array[k + 1]){var temp:int = array[k];array[k] = array[k + 1];array[k + 1] = temp;needSort = true;}}}}3、插入排序(直接插入):每次插入前前面的数组都已经排好序private function insertSort(array:Array):void{var len:int = array.length;for (var i:int = 1; i < len; i++){var temp:int = array[i];for (var k:int = i - 1; k >= 0 && array[k] > temp; k--){array[k + 1] = array[k];}array[k + 1] = temp;}}3、插入排序(二分插入):因为每次插入前前面的数组都已经排好序,所以可以通过二分法找到合适的插入位置private function binaryInsertSort(array:Array):void{var len:int = array.length;var low:int;var high:int;var mid:int;for (var i:int = 1; i < len; i++){var temp:int = array[i];low = 0;high = i - 1;while (low <= high){mid = (low + high) / 2;if (temp > array[mid]){low = mid + 1;}else {high = mid - 1;}}for (var j:int = i - 1; j > high; j--){array[j + 1] = array[j];}array[high + 1] = temp;}}4、希尔排序(简单实用的排序方法):通过改进插入排序方法而来(有间隔的插入排序),虽然代码很好写,但是我一直都不是很懂为什么这样更快private function shellSort(array:Array):void{var len:int = array.length;var distance:int = len;while (distance > 1){distance = distance / 3 + 1;for (var i:int = distance; i < len; i++){var temp:int = array[i];for (var k:int = i - distance; k >= 0 && array[k] > temp; k = k - distance){array[k + distance] = array[k];}array[k + distance] = temp;}}}5、归并排序:利用分治的思想,通过递归,一句话,就是拆分拆分再拆分,合并合并再合并。
八种排序算法
八种排序算法排序算法是计算机科学家们一直在研究的热门话题之一,其中有三个主要的排序类别:比较排序、非比较排序和其他排序。
本文将介绍常见的八种排序算法:冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序和计数排序。
冒泡排序是最基础的排序算法。
它的基本思想是,比较相邻的元素,如果前一个大于后一个,就交换位置。
这种基于比较的排序算法非常简单,但是效率极低,它的时间复杂度为O(n^2),空间复杂度为O(1)。
选择排序是另一种常见的比较排序算法。
它是一种简单的、稳定的排序算法。
它的基本思想是,每次从待排的元素中选出最小(或最大)的元素放到已排好序的序列的末尾。
与冒泡排序相比,选择排序的交换操作次数少,但比较操作次数较多,它的时间复杂度为O(n^2),空间复杂度为O(1)。
插入排序是另一种比较排序算法。
它的基本思想是,每次将一个待排序的数据元素插入到已排序的序列中,使得插入后仍然有序。
插入排序是稳定的排序算法,它的时间复杂度为O(n^2),空间复杂度为O(1)。
归并排序是另一种广泛使用的比较排序算法。
它的基本思想是将原序列逐段分解,然后依次合并,最终得到有序的序列。
它是一种分治算法,它的时间复杂度为O(nlogn),空间复杂度为O(n)。
快速排序是一种广泛使用的分治算法,它的基本思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字比另一部分关键字都要小,然后分别对这两部分记录继续进行排序,直至所有的记录排序完毕。
它的时间复杂度为O(nlogn),空间复杂度为O(nlogn)。
希尔排序是另一种分治算法,它是插入排序的一种改进。
它的基本思想是,将原序列分割为若干个小段,然后对每一段内部进行插入排序,最终得到有序的序列。
它的时间复杂度为O(nlogn),空间复杂度为O(1)。
堆排序是一种比较排序算法,它的基本思想是,将原序列构建成一个大顶堆,然后从堆顶取出最大元素,重新构建堆,取出第二大元素,重新构建堆,直至排序完毕。
头歌数据结构十大经典排序算法
头歌数据结构十大经典排序算法导言在计算机科学中,排序算法是一类常见且重要的算法。
通过对一组元素进行排序,我们可以提高数据的组织性和检索效率。
本文将介绍头歌数据结构十大经典排序算法,包括冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序和基数排序。
冒泡排序冒泡排序是一种简单直观的排序算法。
它通过多次比较和交换相邻元素的方式,将较大(或较小)的元素逐渐交换至数组的一端,从而达到排序的目的。
选择排序选择排序是一种简单且高效的排序算法。
它通过每次选择未排序部分的最小元素,并将其交换至已排序部分的末尾,从而逐步构建有序序列。
插入排序插入排序是一种自然而然的排序算法。
它通过将待排序元素逐个插入已排序序列的正确位置,不断扩大已排序部分的范围,从而完成排序。
希尔排序希尔排序是一种高效的插入式排序算法。
它通过将待排序元素分组,分组内进行插入排序,然后逐步减小分组的大小,以达到整体有序的目的。
归并排序归并排序是一种高效且稳定的排序算法。
它将已排序的子序列合并,不断递归地执行该操作,直到合并整个序列,从而实现排序。
快速排序快速排序是一种高效的分治排序算法。
它通过选择一个基准元素,将序列分割成两部分,并分别对这两部分进行排序,最终将序列有序地整合起来。
堆排序堆排序是一种高效且稳定的排序算法。
它利用堆这种特殊的数据结构,在每次构建堆过程中,获取最大(或最小)元素,并将其放入已排序部分的末尾,从而完成排序。
计数排序计数排序是一种非比较性的排序算法。
它通过统计每个元素出现的次数,计算每个元素应该在有序序列中的位置,从而完成排序。
桶排序桶排序是一种高效的排序算法。
它通过将元素分配到不同的桶中,并对每个桶进行排序,从而得到排序结果。
基数排序基数排序是一种高效的排序算法。
它通过将待排序元素按照个位、十位、百位等进行排序,最终得到有序序列。
结语头歌数据结构十大经典排序算法是计算机科学中不可或缺的内容。
八种排序方法
⼋种排序⽅法⼀.直接(选择)插⼊排序有两种⽅式:升序和降序我使⽤升序直接(简单)插⼊排序:每次向已经排序好的队列⾥⾯找个合适的位置,将值插⼊//笔试和⾯试://1.算法的描述 2.算法的实现 3.效率(时间复杂度和空间复杂度和稳定性)//稳定性定义:如果两个关键值A和A`,如果⼀开始A就在A`前⾯,你排序后A还在A`前⾯,我们就认为是稳定的//怎么看稳定性:看有没有跳跃交换直接插⼊排序:如果数组基本有序,我们就⽤直接插⼊排序,越有序,时间复杂度越⼩,极端情况下为O(n)时间复杂度O(n^2)空间复杂度O(1),稳定的为什么不⽤从前向后找:如果数组有序,则时间复杂度太⼤具体代码实现:#include <stdio.h>#include <assert.h>void InsertSort(int arr[], int len){//循环多少次个数-1//⽤临时量tmp保存关键值,从后向前找,⽐它⼩的或者⾛到了头,就将关键值放到下⼀个位置上assert(arr != NULL);if (NULL == arr)return;int count = 0;int tmp = 0;int j = 0;for (int i = 1; i < len; i++)//控制揭牌后需要排序的次数{tmp = arr[i];for (j = i - 1; j >= 0; j--)//从后向前找{if (arr[j] > tmp)//⽐关键值⼤,则向后移动{arr[j + 1] = arr[j];count++;}else{break;//找到了⽐它⼩的值退出}}arr[j + 1] = tmp;}printf("count %d\n", count);}void Show(int* arr, int len){assert(arr != NULL);if (NULL == arr)return;for (int i = 0; i < len; i++){printf("%d ", arr[i]);}printf("\n");}int main(){int arr[] = { 2,4,6,8,23,98,76,56,74,36,1,3,5,7,99,66,77,88 };InsertSort(arr, sizeof(arr) / sizeof(arr[0]));Show(arr, sizeof(arr) / sizeof(arr[0]));return0;}希尔shell排序:就是⼀种特殊的直接插⼊排序,只不过调⽤了很多次直接插⼊排序,按增量分组要求:增量最后⼀个必须为1,增量保持互素时间复杂度O(n^1.3~1.5),空间复杂度O(1) ,稳定性:发⽣了跳跃交换,所以不稳定例如:分成5组,处理之后的值:分成3组,处理之后的值:最后分成1组,处理之后的值:具体代码实现:#include <stdio.h>#include <assert.h>static void Shell(int arr[], int len, int gap)//gap 分成多少组(间隔){int tmp = 0;int j = 0;int count = 0;for (int i = gap; i < len; i++)//i开始的位置{tmp = arr[i];for (j = i - gap; j >= 0; j = j - gap){if (arr[j] > tmp){arr[j + gap] = arr[j];count++;}else{break;}}arr[j + gap] = tmp;}printf("%d count %d\n", gap, count);}void ShellSort(int arr[], int len){assert(arr != nullptr);if (NULL == arr)return;int dk[] = { 5, 3, 1 };for (int i = 0; i < sizeof(dk) / sizeof(dk[0]); i++){Shell(arr, len, dk[i]);}}void Show(int* arr, int len){assert(arr != NULL);if (NULL == arr)return;for (int i = 0; i < len; i++){printf("%d ", arr[i]);}printf("\n");}int main(){int arr2[] = { 2,4,6,8,23,98,76,56,74,36,1,3,5,7,99,66,77,88 };ShellSort(arr2, sizeof(arr2) / sizeof(arr2[0]));Show(arr2, sizeof(arr2) / sizeof(arr2[0]));return0;}⼆.交换排序冒泡(沉⽯)排序:两两⽐较,⼤的向后挪,⼩的向前挪时间复杂度O(n^2)空间复杂度O(1)稳定的具体代码实现://冒泡排序:两两⽐较,⼤的向后挪void BubbleSort(int arr[], int len){//assert/*int count=0;bool tag = true;*/int tmp = 0;for(int i=0; i<len-1; i++)//次数{//tag = true;for(int j=0;j+1<len-i; j++)//两两⽐较,⼤的向后挪{if(arr[j] > arr[j+1]){tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = tmp;//tag = false;}//count++;}/*if(tag){break;}*/}//printf("count = %d\n", count);}int main(){int arr[] = {2,4,6,8,23,98,76,56,74,36,1,3,5,7,99,66,77,88};BubbleSort(arr, sizeof(arr)/sizeof(arr[0]));Show(arr, sizeof(arr)/sizeof(arr[0]));return 0;}快速排序法每次找到基准值,以基准值为分界线,将数据分成两块,左边的数据都⽐基准值⼩,右边的数据都⽐基准值⼤快速排序,越有序越慢,规则:1.从右向左找⽐基准值⼩的数据,找到后,向左挪动2.从左向右找⽐基准值⼤的数据,找到后,向右挪动3.重复1,2,直到left == right,结束,将基准值放到arr[left] 或者arr[right]内缺点:越有序越慢,不稳定具体实现代码:#include<stdio.h>#include<assert.h>static int Partition(int arr[], int left, int right){int tmp = arr[left];while (left < right)//进来保证有两个值{while(left < right && arr[right] > tmp)right--;if(left == right){break;}arr[left] = arr[right];while(left < right && arr[left] <= tmp)left++;if(left == right){break;}arr[right] = arr[left];}arr[left] = tmp;//arr[right] = tmp;return left;//return right; 因为此时left == right}static void Quick(int arr[], int left, int right){if(left < right){//第⼀种优化:如果有效个数特别少,直接调⽤直接插⼊排序/*if(right-left+1<20 ) //⾃⼰设置有效个数{Insertsort(arr,left, high)return;} // Insertsirt表⽰⼀个插⼊排序类*///第⼆种优化:三数取中/*GetMiddleNumber(arr,left,mid,right);*///第三种优化:防⽌完全有序,⾃⼰打乱⼀下/*Swap(arr,start,rand()%(right-left+1)+start;*///第四种/*if(left < right){int midindex = Partition(arr, left, right);if(left < midindex-1){Quick(arr, left, midindex-1);}if(midindex+1 < right){Quick(arr, midindex+1, right);}}*/int midindex = Partition(arr, left, right);Quick(arr, left, midindex-1);Quick(arr, midindex+1, right);}}//⽤栈static void Quick_stack(int arr[], int left, int right){stack<int> st;if (left < right){int midindex = Partition(arr, left, right);if (left < midindex - 1){st.push(left);st.push(midindex - 1);}if (midindex + 1 < right){st.push(midindex + 1);st.push(right);}}while (!st.empty()){int q = st.top();st.pop();int p = st.top();st.pop();int midindex = Partition(arr, p, q);if (p < midindex - 1){st.push(p);st.push(midindex - 1);}if (midindex + 1 < q){st.push(midindex + 1);st.push(q);}}}void QuickSort(int arr[], int len)//时间复杂度O(nlogn)空间复杂度O(1)不稳定{//assertQuick_stack(arr, 0, len-1);}第⼀种优化代码:void InsertSort(int arr[], int left, int right){int tmp = arr[left];for (int i = left + 1; i <= right; i++){tmp = arr[i];int j = i - 1;while (j >= right && arr[i] > tmp){arr[j + 1] = arr[j];j--;}arr[j + 1] = tmp;}}第⼆种优化代码:void GetMiddleNumber(int arr[], int left, int right){if (arr[left] > arr[right]){Swap(arr, left, right);//交换左右端数据,保证左端较⼩}if (arr[mid] > arr[right]){Swap(arr, left, right);//交换中间和右边,保证中间较⼩}if (arr[mid] > arr[left]){Swap(arr, left, right);//交换中间和左端数据,保证左边不是最⼩的那⼀个}}第三种优化代码:Swap(arr, left, rand() % (end - start + 1) + start);//取⼀个⼩于有效长度随机值+最左端值的下标作为随机基准值的下标与start进⾏交换三.选择排序直接选择(简单选择排序):每次从待排序队列中找到最⼩值,和待排序队列的第⼀位交换即可时间复杂度O(n^2)空间复杂度O(1)不稳定的具体实现代码:#include<stdio.h>#include<assert.h>void SelectSort(int arr[], int len){assert(arr != NULL);if (NULL == NULL)return;int tmp = 0;for (int i = 0; i < len - 1; i++){int m= i;//存放最⼩值下标for (int j = i + 1; j < len ; j++){if (arr[j] <arr[m]){m = j;}}if (m != i)//if判断可省略{tmp = arr[m];arr[m] = arr[i];arr[i] = tmp;}}}void Show(int* arr, int len){assert(arr != NULL);if (NULL == arr)return;for (int i = 0; i < len; i++){printf("%d ", arr[i]);}printf("\n");}int main(){int arr[] = { 2,4,6,8,23,98,76,56,74,36,1,3,5,7,99,66,77,88 };SelectSort(arr, sizeof(arr) / sizeof(arr[0]));Show(arr, sizeof(arr) / sizeof(arr[0]));return 0;}堆排序:堆排序的时间复杂度O(nlogn)空间复杂度O(1)不稳定什么是堆?堆分为两种:⼤顶堆和⼩顶堆两个统称为堆⼤顶堆:⼀个⼆叉树,⽗节点的值⼤于⼦节点的值⼩顶堆:⼀个⼆叉树,⽗节点的值⼩于⼦节点的值什么是树形结构:⼆叉树,树根,深度,叶⼦结点,左孩⼦,右孩⼦,完全⼆叉树,满⼆叉树深度怎么求:log2n+1⼤顶堆和⼩顶堆的关系,和兄弟节点的值⽆关,只和⽗⼦节点有关调整2个要点:1.从最后⼀个⾮叶⼦节点⼦树开始从后向前调整2.调整的时候顺序是从上向下3.升序(⼤顶堆),降序(⼩顶堆)具体实现代码:#include<stdio.h>#include<assert.h>static void HeapAdjust(int arr[], int start, int end)//时间复杂度O(log2n)空间复杂度O(1){int tmp = arr[start];for(int i=2*start+1; i<=end; i=i*2+1)//i? 堆排序效率⾼体现在这⾥i=i*2+1{//1.左右孩⼦都存在//2.只有左孩⼦,没有右孩⼦if(i<end && arr[i] < arr[i+1])//通过i<end保证右孩⼦存在,且arr[i] <arr[i+1]保证左孩⼦⼩于右孩⼦ {i++;//这时候让i指向较⼤的右孩⼦下标}//if判断失败的话,要么没有右孩⼦,要么有右孩⼦但是左孩⼦⽐右孩⼦值⼤,所以i不需要改变if(arr[i] > tmp)//判断较⼤孩⼦节点的值是否⽐⽗节点的值⼤,⼤的话向上覆盖,不然就找到了合适位置 {arr[start] = arr[i];start = i;}else{break;//左右孩⼦中较⼤的孩⼦值⼩于tmp}}arr[start] = tmp;//有两种情况执⾏到这⼀⾏代码:1.触底 2.找到放tmp的合适位置}//堆排序的时间复杂度O(nlog2n)空间复杂度O(1)不稳定void HeapSort(int arr[], int len){//assert//2.调整为⼤顶堆for(int i=(len-1-1)/2; i>=0; i--)//O(nlog2n){HeapAdjust(arr, i, len-1);//}//第⼀个for循环⾛出来,这时已经为⼤顶堆了int tmp = 0;for(int j=0; j<len-1; j++)//j指的是循环的次数(顶部数据和最后⼀个节点交换的次数)//O(nlog2n){//3.将顶部数据和最后⼀个节点进⾏了交换tmp = arr[0];arr[0] = arr[len-1-j];arr[len-1-j] = tmp;//已经将顶部数据和最后⼀个节点进⾏了交换 //4.重复2.3操作HeapAdjust(arr, 0, (len-1-j)-1);}}void Show(int* arr, int len){assert(arr != NULL);if (NULL == arr)return;for (int i = 0; i < len; i++){printf("%d ", arr[i]);}printf("\n");}int main(){int arr[] = { 2,4,6,8,23,98,76,56,74,36,1,3,5,7,99,66,77,88 };HeapSort(arr, sizeof(arr) / sizeof(arr[0]));Show(arr, sizeof(arr) / sizeof(arr[0]));return0;}四.⼆路归并排序⼆路归并排序,⾮递归形式:将两个有序的段合并成⼀个有序的段,直到全部数据在同⼀个段内有序,则完成有序时间复杂度O(n log2n)空间复杂度O(1)稳定的具体代码实现://⼀次归并以gapgap合并static void Merge(int arr[], int len, int gap)//gap 标志⼏⼏合并{int *brr = (int*)malloc(sizeof(int) * len);assert(brr != NULL);int low1 = 0;int high1 = low1 + gap -1;int low2 = high1 + 1;int high2 = low2+gap-1<len ? low2+gap-1 : len-1;//H2 有可能越界若⼩于则low2+gap-1,不是则len-1int i = 0;while(low2 < len)//有两个有序段{while(low1 <= high1 && low2 <= high2)//两个段内头指针都没⾛到尾巴{if(arr[low1] <= arr[low2]){brr[i++] = arr[low1++];}else{brr[i++] = arr[low2++];}}//左边的段⾛到尾,那直接将右边的段内数据向下拷贝到brr内即可while(low2 <= high2){brr[i++] = arr[low2++];}//右边的段⾛到尾,那直接将左边的段内数据向下拷贝到brr内即可while(low1 <= high1){brr[i++] = arr[low1++];}//更改L1L2 H1H1,让指向接下来的两个有序段即可low1 = high2 + 1;high1 = low1+gap-1;low2 = high1 + 1;high2 = low2+gap-1<len ? low2+gap-1 : len-1;}//只有⼀个有序段while(low1 < len){brr[i++] = arr[low1++];}//将brr⾥的全部值拷贝到arr⾥⾯,然后将brr释放for(int j=0; j<len; j++){arr[j] = brr[j];}free(brr);brr = NULL;}void MergeSort(int arr[], int len)//控制合并次数{assert(arr != NULL);if(NULL == arr)return;for(int i=1; i<len; i*=2){Merge(arr, len, i);}}int main(){int arr[] = {2,4,6,8,23,98,76,56,74,36,1,3,5,7,99,66,77,88};MergeSort(arr, sizeof(arr)/sizeof(arr[0]));Show(arr, sizeof(arr)/sizeof(arr[0]));return0;}五.基数排序⼜称桶排序低位优先,所有数据从低位(个)位开始,依次放⼊到对应的⼗个桶内(队列中),再依次从桶中将数据依次取出(出队),直到所有数据循环次数和最⼤位数有关时间复杂度o(n) , 空间复杂度o(n)此时完全有序具体实现代码:#include<stdio.h>#include<assert.h>//基数排序//获取数组中最⼤值的位数static int Get_Figure(int arr[], int len) {int max = 0;for(int i=0; i<len; i++){if(arr[i] > max){max = arr[i];}}int count = 0;while(max != 0)max /= 10;}return count;}//获取n的第fin位的值//1234,2 = 2//234,0 = 4//12345,4 = 1//12345,7 = 0static int Get_num(int n, int fin){for(int i=0; i<fin; i++){n = n / 10;}return n % 10;//return n/(int)(pow((double)10, fin)) % 10;}//⽤⼆维数组调⽤static void Radix(int arr[], int len, int fin)//⼆维数组 fin判断的依据,到底是以什么位排序//时间复杂度O(n)空间复杂度O(n){int bucket[10][20] = {0};//桶int num[10] = {0};//对应的桶中有多少个有效值//所有的数据都以fin位为依据,放到了桶内for(int i=0; i<len; i++)//数组的下标从0开始放{int index = Get_num(arr[i], fin);//获取arr[i]的fin位的值,找到对应的桶bucket[index][num[index]] = arr[i];//放到对⽤的桶中第num[index]位上num[index]++;//对应的桶中有效个数++}//从0-9桶内依次取值到arr⾥int k = 0;for(int i=0; i<10; i++)//⼏号桶{for(int j=0; j<num[i]; j++)//j桶中有效值个数{arr[k++] = bucket[i][j];}}}//⽤链式队列调⽤static void Radix_queue(int arr[], int len, int fin)//时间复杂度O(n)空间复杂度O(n){LQueue queArr[10];for(int i=0; i<10; i++){InitLQueue(&queArr[i]);}for(int i=0; i<len; i++){int index = Get_num(arr[i], fin);Push(&queArr[index], arr[i]);}int k = 0;for(int i=0; i<10; i++){while(!IsEmpty(&queArr[i])){Pop(&queArr[i], &arr[k++]);}}for(int i=0; i<10; i++){Destroy(&queArr[i]);}}void RadixSort(int arr[], int len)//时间复杂度O(dn)空间复杂度(n)稳定{//assertint count = Get_Figure(arr, len);for(int i=0; i<count; i++)//循环的趟数,低位优先{Radix_queue(arr, len, i);}。
各种排序方法总结
各种排序方法总结嘿,朋友们!咱今儿来聊聊排序方法那些事儿。
你说排序重要不?那可太重要啦!就好比你去超市买东西,要是不按顺序拿,那不得乱套呀!咱先说说冒泡排序吧,就好像水里的泡泡,一个一个往上冒。
它呀,慢悠悠地比较相邻的元素,把大的或者小的一点点地挪到合适的位置。
你想想,这多像我们整理书架,一本一本慢慢地调整位置,直到都整整齐齐的。
还有插入排序呢,就像是玩拼图,找到合适的位置把每一块插进去。
一点一点地,让整个序列变得有序。
这不就跟我们整理衣服一样嘛,一件一件按照自己的喜好放好。
选择排序呢,就像是选美比赛!每次都选出最小或者最大的那个元素,放到该放的地方。
这多像我们在一堆糖果里挑出自己最喜欢的那颗呀!快速排序就厉害啦,像个厉害的大侠,刷刷几下就把事情搞定了。
它找到一个基准,然后把比它小的放一边,比它大的放另一边,再分别去排序,效率可高啦!这就好像你要把一群调皮的小朋友分成两队,高个子一队,矮个子一队,多干脆!归并排序呢,像是个沉稳的大师,一步一步慢慢来。
把序列分成两半,再把两半合起来,就变得有序啦。
这不就像搭积木,一块一块地堆起来,最后就成了漂亮的城堡。
排序方法这么多,各有各的特点和用处。
你在生活中是不是也经常用到排序呀?比如安排一天的行程,先做什么后做什么;或者整理自己的房间,把东西都摆得井井有条。
每种排序方法都像是一把神奇的钥匙,能打开有序世界的大门。
我们要根据不同的情况,选择最合适的那把钥匙。
难道不是吗?所以呀,可别小瞧了这些排序方法,它们能帮我们解决好多问题呢!就像我们的生活,有了秩序才能更美好呀!总之,排序方法就是我们生活中的好帮手,让一切都变得有条有理。
大家可得好好掌握它们哦!。
实用的排序技巧
实用的排序技巧排序是计算机科学中常见且重要的算法问题之一,它在各种应用场景中都有广泛的应用。
下面将介绍一些常见且实用的排序技巧。
1. 冒泡排序(Bubble Sort)冒泡排序是一种简单直观的排序算法。
它是通过重复遍历待排序数组,每次比较相邻的两个元素并交换位置,最终将最大(或最小)元素“冒泡”到数组的末尾。
冒泡排序的时间复杂度为O(n^2),其中n是数组的长度。
2. 插入排序(Insertion Sort)插入排序是一种类似于整理扑克牌的排序算法。
它通过构建有序序列,对于未排序的数据,依次在有序序列中找到合适的位置插入。
插入排序的时间复杂度为O(n^2),但在实际应用中,它对于小规模或部分有序的数组有较好的性能。
3. 快速排序(Quick Sort)快速排序是一种分而治之的排序算法。
它选择一个基准元素,并通过一趟排序将待排序数组分割成两个子数组,其中一个子数组的所有元素都小于基准元素,另一个子数组的所有元素都大于基准元素,然后对两个子数组递归地进行快速排序。
快速排序的时间复杂度为O(nlogn),其中n是数组的长度。
4. 归并排序(Merge Sort)归并排序是一种稳定的排序算法。
它通过将待排序数组递归地分成两部分,分别对两部分进行排序,然后将两个有序数组合并成一个有序数组。
归并排序的时间复杂度为O(nlogn),它是一种比较占用内存但效率较高的排序算法。
5. 堆排序(Heap Sort)堆排序是一种利用堆的数据结构进行排序的算法。
它将待排序数组构建成一个最大堆(或最小堆),然后依次取出堆顶元素并将其放到数组的末尾,再重新调整堆。
堆排序的时间复杂度为O(nlogn),堆排序不稳定,但它的空间复杂度较低。
6. 计数排序(Counting Sort)计数排序是一种非比较排序算法。
它通过统计数组中各元素出现的次数,并计算出每个元素的排名,然后根据排名构建有序数组。
计数排序的时间复杂度为O(n+k),其中n是数组的长度,k是数组中元素的范围。
8种常见排序算法总结
8种常见排序算法总结1,选择排序基本思想:在要排序的⼀组数中,选出最⼩(或者最⼤)的⼀个数与第1个位置的数交换;然后在剩下的数当中再找最⼩(或者最⼤)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第⼆个数)和第n个元素(最后⼀个数)⽐较为⽌。
2,希尔排序基本思想:先将整个待排序的记录序列分割成为若⼲⼦序列分别进⾏直接插⼊排序,待整个序列中的记录“基本有序”时,再对全体记录进⾏依次直接插⼊排序。
操作⽅法:选择⼀个增量序列t1,t2,…,tk,其中ti>tj,tk=1;按增量序列个数k,对序列进⾏k 趟排序;每趟排序,根据对应的增量ti,将待排序列分割成若⼲长度为m 的⼦序列,分别对各⼦表进⾏直接插⼊排序。
仅增量因⼦为1 时,整个序列作为⼀个表来处理,表长度即为整个序列的长度。
3,快速排序快速排序是通常被认为在同数量级(O(nlog2n))的排序⽅法中平均性能最好的。
但若初始序列按关键码有序或基本有序时,快排序反⽽蜕化为冒泡排序。
为改进之,通常以“三者取中法”来选取基准记录,即将排序区间的两个端点与中点三个记录关键码居中的调整为⽀点记录。
快速排序是⼀个不稳定的排序⽅法。
4,堆排序操作对象是数组!!不是树!!初始时把要排序的n个数的序列看作是⼀棵顺序存储的⼆叉树(⼀维数组存储⼆叉树),调整它们的存储序,使之成为⼀个堆,将堆顶元素输出,得到n 个元素中最⼩(或最⼤)的元素,这时堆的根节点的数最⼩(或者最⼤)。
然后对前⾯(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次⼩(或次⼤)的元素。
依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。
称这个过程为堆排序。
因此,实现堆排序需解决两个问题:1. 如何将n 个待排序的数建成堆;2. 输出堆顶元素后,怎样调整剩余n-1 个元素,使其成为⼀个新堆。
⾸先讨论第⼆个问题:输出堆顶元素后,对剩余n-1元素重新建成堆的调整过程。
八种常见的排序算法
⼋种常见的排序算法插⼊排序1.直接插⼊排序原理:将数组分为⽆序区和有序区两个区,然后不断将⽆序区的第⼀个元素按⼤⼩顺序插⼊到有序区中去,最终将所有⽆序区元素都移动到有序区完成排序。
要点:设⽴哨兵,作为临时存储和判断数组边界之⽤。
实现:void InsertSort(Nodetype p[],int length){int i,j;//分别为有序区和⽆序区指针for(i=1;i<length;i++)//逐步扩⼤有序区{j=i+1;if(p[j]<p[i]){p[0]=p[j];//存储待排序元素while(p[0]<p[i])//查找在有序区中的插⼊位置,同时移动元素{p[i+1]=p[i];//移动i--;}p[i+1]=p[0];//将元素插⼊}i=j-1;//还原有序区指针}}2.希尔排序原理:⼜称增量缩⼩排序。
先将序列按增量划分为元素个数相同的若⼲组,使⽤直接插⼊排序法进⾏排序,然后不断缩⼩增量直⾄为1,最后使⽤直接插⼊排序完成排序。
要点:增量的选择以及排序最终以1为增量进⾏排序结束。
实现:void ShellSort(Nodetype p[],int d){while(d>=1)//直到增量缩⼩为1{Shell(p,d);d=d/2;//缩⼩增量}}void Shell(Nodetype p[],int d){int i,j;int length=strlen(p);for(i=d+1;i<length){if(p[i]<p[i-d]){p[0]=p[i];j=i-d;while(j>0&&p[j]>p[0]){p[j+d]=p[j];j=j-d;}p[j+d]=p[0];}}}交换排序1.冒泡排序原理:将序列划分为⽆序和有序区,不断通过交换较⼤元素⾄⽆序区尾完成排序。
要点:设计交换判断条件,提前结束以排好序的序列循环。
实现:void BubbleSort(Nodetype p[]){int i,j;int ischanged;//设计跳出条件for(j=n-1;j<0;j--){ischanged=0;for(i=0;i<j;i++){if(p[i]>p[i+1])//如果发现较重元素就向后移动{int temp=p[i];p[i]=p[i+1];p[i+1]=temp;ischanged=1;}}if(!ischanged)//若没有移动则说明序列已经有序,直接跳出break;}}2.快速排序原理:不断寻找⼀个序列的中点,然后对中点左右的序列递归的进⾏排序,直⾄全部序列排序完成,使⽤了分治的思想。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
*置移到数组最后一个元素时排序结束(此时基准左边所有元素
*均递增有序,而基准为最后一个元素,故完成排序)。
*/
void Selectsort(int A[],int n)
{
int i,j,min,temp;
for(i=0;i<n;i++)
data[1]=data[i];
data[i]=temp;
HeapAdjust(data,1,i-1);
}
}
void HeapAdjust(int data[],int s,int m) /*排列成堆的形式*/
{
int j,rc;
rc=data[s]; /*保存处理元素*/
for(j=2*s;j<=m;j*=2) /*处理父亲元素*/
{
if(j<m && data[j]<data[j+1]) ++j; /*取较大的孩子节点*/
{
int mid;
data[0]=data[low];
mid=data[low];
while(low < high)
{
while((low < high) && (data[high] >= mid))
{
--high;
}
data[low]=data[high]; /*从high的位置开始往low的方向找,找到比data[low]小的元素,存到data[low]中*/
常见经典排序算法
1.希尔排序
2.二分插入法
3.直接插入法
4.带哨兵的直接排序法
5.冒泡排序
6.选择排序
7.快速排序
8.堆排序
一.希尔(Shell)排序法(又称宿小增量排序,是1959年由D.L.Shell提出来的)
/* Shell排序法*/
#include <stdio.h>
void sort(int v[],int n)
*堆的定义n个元素的序列{k1,k2,...,kn}当且仅当满足下列关系时,
*称为堆:
* ki<=k2i ki<=k2i+1 (i=1,2,...,n/2)
*或
* ki>=k2i ki>=k2i+1 (i=1,2,...,n/2)
*堆排序思路:
*建立在树形选择排序基础上;
*将待排序列建成堆(初始堆生成)后,序列的第一个元素(堆顶元素)就一定是序列中的最大元素;
*自身进行比较,很明显这个时候说明位置i之前的数字都比input[i]小
*位置i上的数字不需要移动,直接进入下一轮的插入比较。
*
*/
void InsertionSortWithPiquet(int input[],int len)
{
int i,j;
for (i = 2; i < len; i++) /*保证数组input第一元素的存储数据无效,从第二个数据开始与它前面的元素比较*/
{
temp = a[i];/*保存但前元素*/
low = 0;
high = i-1;
while (low <= high) /*在a[low...high]中折半查找有序插入的位置*/
{
mid = (low + high) / 2; /*找到中间元素*/
if (a[mid] > temp) /*如果中间元素比但前元素大,当前元素要插入到中间元素的左侧*/
*最后将这个刚空出来的位置装入中间值(data[low]=data[0]),
*这样一来比mid大的都会跑到mid的右侧,小于mid的会在左侧,
*最后一行,返回的low是中间元素的位置,左右分别递归就可以排好序了。
*/
int Partition(int data[],int low,int high)
*从a[0:n-1]中选择一个元素作为middle,
,使得left中的元素都小于
*等于支点,而right中的元素都大于等于支点
*递归地使用快速排序方法对left进行排序
*递归地使用快速排序方法对right进行排序
*所得结果为left+middle+right
*将其与序列的最后一个元素交换,将序列长度减一;
*再将序列建成堆(堆调整)后,堆顶元素仍是序列中的最大元素,再次将其与序列最后一个元素交换并缩短序列长度;
*反复此过程,直至序列长度为一,所得序列即为排序后结果。
**************************************************************/
{
min=i;
for(j=i+1;j<=n;j++) /*从j往前的数据都是排好的,所以从j开始往下找剩下的元素中最小的*/
{
if(A[min]>A[j]) /*把剩下元素中最小的那个放到A[i]中*/
{
temp=A[i];
A[i]=A[j];
A[j]=temp;
}
}
}
}
七.快速排序
/*快速排序(quick sort)。在这种方法中,
void Bublesort(int a[],int n)
{
int i,j,k;
for(j=0;j<n;j++) /*气泡法要排序n次*/
{
for(i=0;i<n-j;i++) /*值比较大的元素沉下去后,只把剩下的元素中的最大值再沉下去就可以啦*/
{
if(a[i]>a[i+1]) /*把值比较大的元素沉到底*/
}
}
/*要注意看清楚下面的数据之间是如何替换的,
*首先选一个中间值,就是第一个元素data[low],
*然后从该元素的最右侧开始找到比它小的元素,把
*该元素复制到它中间值原来的位置(data[low]=data[high]),
*然后从该元素的最左侧开始找到比它大的元素,把
*该元素复制到上边刚刚找到的那个元素的位置(data[high]=data[low]),
{
input[j + 1] = input[j]; /*一边找一边移动元素*/
input[j] = temp;
}
}
}
四.带哨兵的直接排序法
/**
*带哨兵的直接插入排序,数组的第一个元素不用于存储有效数据
*将input[0]作为哨兵,可以避免判定input[j]中,数组是否越界
*因为在j--的过程中,当j减小到0时,变成了input[0]与input[0]
{
high = mid-1;
}
else /*如果中间元素比当前元素小,但前元素要插入到中间元素的右侧*/
{
low = mid+1;
}
} /*找到当前元素的位置,在low和high之间*/
for (j=i-1; j>high; j--)/*元素后移*/
{
a[j+1] = a[j];
}
a[high+1] = temp; /*插入*/
}
}
三.直接插入法
/*直接插入法*/
void InsertionSort(int input[],int len)
{
int i,j,temp;
for (i = 1; i < len; i++)
{
temp = input[i]; /*操作当前元素,先保存在其它变量中*/
for (j = i - 1;j>-1&&input[j] > temp ; j--) /*从当前元素的上一个元素开始查找合适的位置*/
* n个元素被分成三段(组):左段left,
*右段right和中段middle。中段
*仅包含一个元素。左段中各元素都小于等
*于中段元素,右段中各元素都大于等于中
*段元素。因此left和right中的元
*素可以独立排序,并且不必对left和
* right的排序结果进行合并。
*使用快速排序方法对a[0:n-1]排序
while((low < high) && (data[low] < mid)) /*新得到的data[low]肯定小于原来的data[low]即mid */
{
++low;
}
data[high]=data[low]; /*从low的位置开始往high的方向找,找到比data[high]大的元素,存在data[high]中*/
{
input[0] = input[i];
for (j = i - 1; input[j] > input[0] ; j--)
{
input[j + 1] = input[j];
input[j] = input[0]; /* input[j]一直都是排序的元素中最大的那一个*/
}
}
}
五.冒泡法
/*冒泡排序法*/
{
int gap,i,j,temp;
for(gap=n/2;gap>0;gap /= 2) /*设置排序的步长,步长gap每次减半,直到减到1 */
{
for(i=gap;i<n;i++) /*定位到每一个元素*/
{
for(j=i-gap;(j >= 0) && (v[j] > v[j+gap]);j -= gap ) /*比较相距gap远的两个元素的大小,根据排序方向决定如何调换*/