目录:
一;
(1):冒泡排序
( 2):选择排序
(3):插入排序
(4):希尔排序
(5):计数排序
(6):快速排序
(7):归并排序
(8):堆排序
二:八大排序时间复杂度及稳定性差异
三:个人总结
一:冒泡排序
1:思路
将一组数组中从下标为1(也可从零开始,主要看当前数与前一个数比较还是后一个数)开始循环与前一个数比较(假定排序为升序),如果当前数大于钱一个数就交换,如此循环到数组最后一位数结束一趟循环。
第二趟循环依次从1开始重新循环比较,唯一的差异就是每趟循环后重新一趟循环次数就会减少一次,
二:选择排序
1:思路
首先从数组中(特定的范围中)从第下标为1的数循环比较求出最大值和最小值,求最大值最小值时可临时决定数组第一位数为最大值,最小值。求出最大值后将最大值与begin交换,最小值与end交换为一趟。
其次出去数组中最大值和最小值后为一趟新的范围,循环(首先)的步骤。
3:插入排序
1:思路
首先确定当前数的下一个位置为插入值。(升序为例)如果当前值大于插入值,则直接将当前值移到下一位,如果当前值小于插入值,则插入值放入当前值的下一位,为一趟循环。每次排序实则是当前值将插入值放到合适的位置。
其次从第一个数开始确定当前数,end的范围随着i的增加而增加来重复首先的步骤。
4:希尔排序
1:思路
希尔排序实际是多个插入排序的组合,一般用于大量数据之中。
首先便是对于数据进行与排序,一维数组中的数据分为n个个数数为gap的小组(有可能n不是整数,具体看数组与gap的关系)这个,然后从第一个数轮流对各个小组进行插入排序,与插入排序不同的是它不是一趟排完,而是多次多组进行。
其次,随着gap步的一趟完成,gap随着 n / 3 的变化不断循环(首先的步骤),当预排序结束的时候,即gap = 1时实现插入排序。。
5:计数排序
首先要求出计数数组的范围,即求出排序数组最大值和最小值,
其次通过循环求出排序数组对应数在计数数组的下标:a[i] - min;
然后 排序数组下标 j == a[i] - min 来计数。(看排序数组与计算数组下标的关系);
最后通过循环将排序数组的值 j + min一次放入排序数组中。
。
6:快速排序
1:haro法(以升序为例)
首先通过left 和 right(必须新建两个变量),先确定首元素为基准数,通过左边找大,右边找小,
左定基准值右边先走,当右边和左边依次找到大 小时,便让他们交换值,当right和left相遇时
便让相遇位置与key交换为一趟。
然后通过左递归,右递归,由递归不断划分区间( 对半取一)的方式来不断实现(首先的步骤),递归的结束方式为 它们的区间不存在或者不相等的时候(begin >= end).
2:挖坑法
首先用key保存数组首元素(切不可用a[key]保存,它是一个变换的值)行成一个坑位。然后从右边开始right寻找最大值将右边的值赋值目前的left(实际将坑位换到右边),左边left寻找最小值将左边的值赋值给右边目前的right(是即将坑位换到左边),相遇后再把key值赋值给相遇位置(形成key左边的值小于key,右边的值大于key)。
然后通过左递归,右递归,由递归不断划分区间( 对半取一)的方式来不断实现(首先的步骤),递归的结束方式为 它们的区间不存在或者不相等的时候(begin >= end).
3:双指针法(以升序为例)排序定区间‘
1:额外创建一个指针cur它所指向的下标初始值比prev大一,如果a[cur] < key,则prev + 1 ,a[cur]与a[prev]交换。如果否则cur+1为一趟,直到cur指向cur >end结束后将此时的a【prev】与key交换直到cur>end。
改良版
1的方法会造成·++prev与cur相同时还会交换,我们的目的是让符合a[cur] < key的条件下,++prev != cur下,a[cur]与a[key]交换更加简便。
4:最终版
1:三数取中
三数取中的目的为取出三数中的中间值;(防止一直key一直取得是数组里面最小的值,防止快排得时间复杂度为O(N^2));
首先先将a[key]元素为key(防止减少比较次数),然后将a[key]与a[mid]进行交换。
3:增加插入排序;
由于递归越往向下递归它的递归次数就会越来越多,最后一层可占总数的%50,为了减少递归调用次数,可以在最后几层(end-begin >=20)采用插入排序来减少消耗。
先进行普通快速排序后当end - begin >= 20 时,便在这个栈里面实行插入排序
5:快排的非递归
首先:根据快排的实质为初始区间,排序分区间,定新区间,依次递归循环,直到begin >= end;
其次:当调用多次递归时可能会出现爆栈,所以我们可以通过栈来模拟递归,减少内存消耗。
排序定区间:
首先:根据栈先进后出的特点,将初始区间按右区间,左区间的方式放入栈中。
其次: 依次出栈,取取它们的区间来进行快速排序,得到key新的下标;
分新区间:
首先:然后依次将整个区间分为【begin,key-1],[key + 1,end]从由右向左进行入栈;
其次; 考虑特殊情况,左右两个区间情况不同,结果不同。
左区间符合区间时(left < key -1)左区间入栈,
右区间符合区间时(key+1 < right)右区间入栈。
6:归并排序
首先:归并排序的算法核心为:分治;
将大区间分成小区间。
其次:将小区间进行合并归并,将数组新的顺序对应赋值个旧的数组。
归并排序的非递归:(后序)
首先:根据归并排序的递归版本,最小调用递归为2个数(gap =1)循环归并;2个区间四个变量一次循环定变量,两次循环看归并个数gap。直到结束为一趟。(与递归版本不同的是随着gap改变它一趟递归并不是所有数都要归并的,但是随着趟数的改变最终所有数都会归并到);
其次:当gap随着一趟循环的结束而变大,从0开始gap个数为一组进行循环排序。gap最大个数为size-1,因为整个归并 排序必须要有两个区间进行归并。
最后:gap确定时,一趟排序完成后再将tmp数组的数全部赋值给a数组。
最终:在求对个变量的对应区间时,可用假设法,多次举例法,通过假设法减少干扰,通过结果求得规律
八大排序时间复杂度及稳定性归纳:
1:
1:堆排序和归并排序不受数组顺序变化的影响,都为O(N*logn)。(看循环)
2:选择排序也不受数组顺序变化影响,但时间复杂度为O(N^2).
3: 快速排序,冒泡排序,插入排序时间复杂度最差为O(N^2)
4:归并排序,堆排序一个有递归调用和数组开辟,一个有递归调用,前者
主要为数组开辟,后者主要影响为递归调用。