今天参加了百度的笔试,发现各种囧,各种弱,看来得好好加强啦!
正如很多公司笔试面试一样,百度也免不了会考你几道关于排序的算法。排序还真的成为了各大IT公司的宠儿了,那这里我把它总结总结吧……
对于A[n] = {a1, a2, a3,……, an}这一数组,来把各种排序算法一一讲解吧!
小插入一把,今天被问到什么是排序算法的稳定性,我囧了,回来百度了一下,所谓稳定性:
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,
ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。
一、插入排序(这里数组的元素均从a[1]开始)
思想:j=2-->n,i=j-1-->0.依次将a[j]与a[i]--->a[1]比较,如果a[j]<a[i],则将a[i]往后移一位,直到找到合适于a[j]的位置,然后将a[j]插入进去。
伪代码:
Insertion_sort( a )
for j=2 -->n
key = a[j]
// Insert a[j] into a[1....j-1]
i = j-1
while(i>0 and a[j]<a[i])
a[i+1] = a[i]
i = i -1
a[i+1] = key
最坏的情况:完全反序,那么时间复杂度为:O(n^2)
稳定性分析:插入排序是在一个有序的小序列的基础上进行插入。当然一开始,这个有序序列的元素只有一个元素。比较从有序序列的末尾开始,即从最大者开始比较。如果k
比最大元素还在,则直接放其后面。如果比其小,则一直往前比较,直至找到一个合适的位置。如果碰到相等的元素,则是把它放在该元素的后面。因此该排序
算法是稳定的。
二、归并排序
归并算法采用分治法。(1)分解:将待排序数组a[n]分成各具有n/2个元素的子数组。(2)解决:使用归并排序递归地排序两个子序列。(3)合并:合并两个已排序的子序列以产生正确的排序数组。
伪代码:
Merge_Sort(a[ ] ,p ,r)
if p<r
q = [ p + r ]/2
Merge_Sort( a[ ] , p ,q)
Merge_Sort( a[] , q+1 , r)
Merge(a , p , q, r)
Merge(a[],p,q,r)
l_length = q - p +1
r_length = r-q
create new arrays L[l_length], R[r_length]
for i = 1 to l_length
L[i] = a[p+i-1]
for j = 1 to r_length
R[j] = a[q+j]
compare L[n] and R[n]
i = j = 1
for k = p to r
while i != l_length and j != r_length
if L[i]<R[j]
a[k] = L[i]
i++
else
a[k] = R[j]
j++
if i==l_length
a[k] = R[j]
else
a[k] = L[i]
时间复杂度分析:T(n) = 2T(n/2) + O(n) ---->O(n) = nlgn
稳定的排序算法。
三、快速排序
思想:将数组a[p...r]划分为两个子数组a[p....q-1] 和 a[q+1...r]。使得a[p....q-1]中每个元素都比a[q]小,a[q+1....r]中每个元素都比a[q]大。然后利用递归算法对子数组这样排序。
关键在于,如何分解数组。
Partition(a[] , p ,r)
x = a[r]
i = p-1, j = p
for j = p-->r-1
if a[j]<x
i++
exchange a[i]<-->a[j]
j++
exchange a[i+1]<->x
return i+1
Quick_Sort(a[] ,p ,r)
if p<r
q = Partition(a[],p,r)
Quick_Sort(a[],p,q-1)
Quick_Sort(a[],q+1,r)
时间复杂度:O(nlgn)
不稳定性算法
四、冒泡排序法
Bubble_Sort(a[])
for i = 1->n
do for j=n-->i+1
if a[j]<a[j-1]
exchange a[j],a[j-1]
后面再讲堆排序吧……