排序
插入排序
|
|
描述
⒈ 从第一个元素开始,该元素可以认为已经被排序
⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描
⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置
⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
⒌ 将新元素插入到下一位置中
⒍ 重复步骤2~5算法复杂度
如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需
(n-1)
次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次
。插入排序的赋值操作是比较操作的次数加上(n-1)
次。平均来说插入排序算法的时间复杂度为O(n^2)
。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择稳定性
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
希尔排序
|
|
描述
希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因DL.Shell于1959年提出而得名
基本思想:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率较高。
以n=10的一个数组 3,2,5,8,6,0,1,4,9,7为例(位置间隔为gap的为同一组,每次对同一组的数据进行直接插入排序)
第一次 gap = 10 / 2 = 5 分为五组(3,0),(2,1),(5,4),(8,9) ,(6,7) 排序完为 (0,3),(1,2),(4,5),(8,9) ,(6,7)
3 2 5 8 6 0 1 4 9 7 → 0 1 4 8 6 3 2 5 9 7
第二次 gap = 5 / 2 = 2 分为两组(0,4,6,2,9),(1,8,3,5,7) 排序完为 (0,2,4,6,9),(1,3,5,7,8)
0 1 4 8 6 3 2 5 9 7 → 0 1 2 3 4 5 6 7 9 8
第三次 gap = 2 / 2 = 1 分为一组(0,1,2,3,4,5,6,7,9,8) 排序完为(0,1,2,3,4,5,6,7,8,9)
0 1 2 3 4 5 6 7 9 8 → 0 1 2 3 4 5 6 7 8 9
第四次 gap = 1 / 2 = 0 排序完成得到数组
0 1 2 3 4 5 6 7 8 9
归并算法
|
|
定义
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为
二路归并
。描述
1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2.设定两个指针,最初位置分别为两个已经排序序列的起始位置
3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
4.将另一序列剩下的所有元素直接复制到合并序列尾算法复杂度
时间复杂度为O(nlog₂n) 这是该算法中最好、最坏和平均的时间性能。
空间复杂度为 O(n)
比较操作的次数介于(nlogn) / 2和nlogn - n + 1。
赋值操作的次数是(2nlogn)。归并算法的空间复杂度为:0 (n)
归并排序比较占用内存,但却是一种效率高(仅次于快速排序)且稳定的算法。
冒泡排序
|
|
描述
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较算法复杂度
平均时间复杂度也是:O(n^2)
最优的情况下时间复杂度为:O(n)
最差的情况下时间复杂度为:O(n^2)稳定性
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
快速排序
|
|
描述
快速排序是对冒泡排序的一种改进。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。算法复杂度
快速排序的平均时间复杂度也是:O(nlogn)
快速排序最优的情况下时间复杂度为:O( nlogn )
最差的情况下时间复杂度为:O( n^2 )
最优的情况下空间复杂度为:O(logn) ;每一次都平分数组的情况
最差的情况下空间复杂度为:O( n ) ;退化为冒泡排序的情况
选择排序
NSArray *)selectSortArray:(NSArray *)originArray
{
NSMutableArray * sortArray = [originArray mutableCopy];
NSNumber * min;
for (NSInteger i = 0; i < sortArray.count - 1; i ++)
{
min = sortArray[i];
for (NSInteger j = i + 1; j < sortArray.count; j ++)
{
if ([min compare:sortArray[j]] == NSOrderedDescending) {
NSNumber * temp = sortArray[j];
sortArray[j] = min;
min = temp;
}
}
sortArray[i] = min;
}
return sortArray;
}
- (
描述
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
时间复杂度
选择排序的交换操作介于 0 和 (n - 1) 次之间。选择排序的比较操作为 n (n - 1) / 2 次之间。选择排序的赋值操作介于 0 和 3 (n - 1) 次之间。比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+…+1=n*(n-1)/2。交换次数O(n),最好情况是,已经有序,交换0次;最坏情况交换n-1次,逆序交换n/2次。交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。