关闭

各种排序,白话版原理思想

180人阅读 评论(0) 收藏 举报
分类:

内部排序:

一般来说:存在不相邻交换的排序算法是不稳定的,相邻交换的排序算法是稳定的;对于相邻交换的稳定排序算法,通过控制交换条件可以转换成不稳定排序算法;冒泡、插入、归并和基数排序是稳定的;选择、快速、希尔和堆排序是不稳定的。

 

一、冒泡排序

从数组的头部开始循环,判断相邻的两个元素,如果前一个元素大于后一个元素,那么交换两者,直到这一次过程将待排序部分中的最大值,移到最后。每一次循环过程就像冒泡一般将最大值一步一步移到最后,时间复杂度O(n2),稳定排序,原址排序。

原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,

这样一趟过去后,最大或最小的数字被交换到了最后一位,

然后再从头开始进行两两比较交换,直到倒数第二位时结束。

一直循环到只剩下一个元素不能再进行交换。

void bubble_sort(T arr[], int len) 

{ int i, j;

 T temp;

 for (i = 0; i < len - 1; i++)

     for (j = 0; j < len - 1 - i; j++)

       if (arr[j] > arr[j + 1]) 

        { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; }}

 

二、插入排序

将数组看做两部分,一部分是以排好序的,一部分是未排好序的,刚开始将第一个元素看做是已经排好序的,对于未排好序的元素,然后依次从后遍历排好序的数组,如果它比元素小则交换两者,直到找到比其小的元素。时间复杂度O(n2),稳定排序,就地排序

 

三、选择排序

首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾。以此递归。(就地,但是非稳定的,以为发生交换是不遵循相对顺序的)。

 

四、希尔排序

先取一个正整数,开始一般为数组长的二分之一,然后讲数组中所有间隔为d的,放在一起进行插入排序,然后再取一个数为原来正整数的二分之一重复以上过程,直到该值为1 为止。(就地,非稳定性

 

五、归并排序

将待排序的数组分为两个区间,递归的对两个区间进行归并排序,然后将已排序好的两个区间进行合并,递归的终止条件是区间的大小为1。(需要额外的数组,稳定排序)

 

六、快速排序

先确定一个主元,然后把比它小的放在左边,大的放在右边(具体的实现是从两边找,找到一对后交换),最后得到这个中间值位置,然后对两边分别使用这个过程(递归)。递归的终止也是条件子区间的大小为1。(就地排序,非稳定)

七、堆排序

首先建立一个最大堆,该数组的最大元素就在最大堆的根节点,然后每次交换数组最后的一个元素和根元素,这样最大值就位于了它应该在的位置,然后对最大堆进行调整,在递归的交换新数组的最后一个元素和根元素。(就地排序,非稳定)

八、基数排序

要保证遍历的稳定性,首先从个位从大到小排列,然后递进的到十位、百位。

时间复杂度O(n),看似比快排更快,但是在这两个表达式中,隐藏在时间复杂度中的常量因子是不同的,在处理N个关键字时,尽管基数排序的循环次数较少,但每一轮消耗的时间要长得多,并且快排更适合底层硬件实现,并且基数排序不是就地排序,需要额外的空间。

 

九、计数排序

对于每一个输入元素x,确定小于x的元素个数,这样就可以确定x元素的位置,然后从数组后依次确定数组中元素的位置,(需要两个辅助数组,存放新数组,存放大于等于下标的元素个数,稳定排序,从后往前的

 

 

十、桶排序

根据数据的特征分为n个桶,对于每个数据都会落入其中的一个桶中,然后先后对每个桶进行排序,然后遍历每个桶,把桶中元素列出来即可(需要辅助的数据结构,稳定排序)

 

外部排序:

十一、多路并归

外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装人内存的部分,分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行归并排序。(对于K路归并,如果简单的找出这k路的最小值,需要k-1次比较,采用胜者树或者败者树,则比较次数为logK次,每次比较之后,得到最小者放入其他文件中,然后再从最小的那个文件取出下一个元素,直到所有K路  全部为空为止)


对于每两路采用胜者树方法,较小者进入下一轮,直到本轮决出最小者。

 

TOP K(最小的K)算法:

1.     随机化的快速排序算法,从每次需要排序的区间随机选取轴值,然后分两边,得到轴值的位置信息pos,如果pos小于K则丢弃(START,K-1),反之丢弃(K+1,END)

2.     最大堆算法:建立K个值的最大堆,如果当前值大于根节点则不管,如果小于根节点,则交换两者,然后对最大堆进行调整。

 

海量数据的处理:

方法一:不能全部加入内存,根据hash划分成多个小文件,然后对小文件进行处理,再归并。

方法二:bitmap,布隆过滤器等,1G个内存大概能处理1亿的数据。

 

1. 数亿个重复字符串,找出出现次数最多的K个字符串:

首先用Hash表记录每个字符串出现的次数,然后建立一个K大小的最小堆,对于后面的每个字符串比比较其出现的次数和根节点出现次数的大小,小于则跳过,大于则替代根节点,然后对最小堆进行调整。(在统计次数方面,也可以采用tire数来计算字符串出现的次数,然后再用最小堆来找出最多的K个字符串)

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:103729次
    • 积分:2591
    • 等级:
    • 排名:第14108名
    • 原创:105篇
    • 转载:207篇
    • 译文:0篇
    • 评论:9条
    最新评论