标签:
不管是C++还是JAVA,都有相应的库提供排序函数。比如,c++中<algorithm>提供了sort函数。不过,能了解常见排序算法的原理,在面试或工作中都有一定的帮助。下面,对常见排序算法进行梳理。
常见的排序算法有:插入排序,选择排序,冒泡排序,希尔排序,快速排序,归并排序,基数排序,堆排序。
一、插入排序
1,思想:提到插入排序,一个朋友给我举了一个非常传神的栗子,简单形象,通俗易懂。大家都有打扑克牌吧,一般来说,我们抓牌后都是按顺序放在手中。每当我们新抓一张牌,就把这张牌插入到排好序的手牌中。而这正符合插入排序的思想,在有序的序列中插入新的元素。
7 6 1 5 3, 开始时,我们有一张手牌7,它自己是有序的(一个元素),然后我们抓起来一张6,比7小,两者交换。
6 7 1 5 3,然后来了一张1,拿它和有序序列6,7比较,插入到起始位置
1 6 7 5 3,然后来了一张5,拿它和有序序列1,6,7比较,插入
1 5 6 7 3,最后来了一张3,拿它和有序序列1,5,6,7比较,插入
1 3 5 6 7,得到排序结果
show me the code.我们先看看C++的实现代码。
for (int i=1; i<v.size(); i++){
int key = v[i];
int j = i-1;
while (j >= 0 && v[j] > key){
v[j+1] = v[j];
j--;
}
v[j+1] = key;
}
然后,我们再看看python实现。
def insert_sort(lists):
count = len(lists)
for i in range(1,count)
key = lists[i]
j = i - 1
while j >= 0:
if lists[i] > key:
lists[j + 1] = lists[j]
lists[j] = key
j -= 1
return lists
值得注意的是,c++实现和python实现在交换数据这个细节上不同。C++, 如果排序序列中的值比key小且j>=0,我依次把排序序列往右移,直到不满足时,我们把key赋给那个位置。而python中,满足条件时,交换相邻两个元素。
实现细节不同,但两者思想一致。
2,时间复杂度
外层循环为待排序序列个数n,内循环中,如果考虑完全你虚的情况,则需交换数据(移动数据)n次,所以时间复杂度为O(N^2).
二、选择排序
选择排序的思想简单粗暴。从序列中找到最小值,放到第一个位置,然后在剩余元素中找最小值放在第二位置.....bulabula.......。有一种很通俗的说法,喧杂排序是固定位置找元素,而插入排序是固定元素找位置。很形象。
for(int i=0; i<v.size(); i++){
int min = v[i];
int temp;
int index = i;
for(int j = i + 1; j < v.size(); j++){
if(v[j] < min){
min = v[j];
index = j;
}
}
temp = v[i];
v[i] = min;
v[index]= temp;
}
同样,我们看看python实现。
def select_sort(lists):
count = len(lists)
for i in range(0, count):
min = i
for j in range(i + 1, count):
if lists[min] < lists[j]:
min =j
lists[min], lists[i] = lists[i], lists[min]
return lists
三、冒泡排序
1,思想。冒泡排序,人如其名,如果考虑升序的话,就是比较相邻元素大小,将小的元素左移,大的元素右移,经过一轮移动,可以将最小元素移到最左边,或者最大元素移到最右边。就像气泡一样上浮(小元素左移),或者石头落入水底(大元素右移)。两种移动方法,可凭自己喜欢选择。
时间复杂度O(N^2).
C++代码,小元素左移。
for (int i=0; i<v.size(); i++){
int temp = 0;
for(int j=v.size()-1; j > i; j--){
if (v[j] < v[j-1]){
temp = v[j];
v[j] = v[j-1];
v[j-1] = temp;
}
}
}
python代码,大元素右移。
def bubble_sort(lists):
count = len(lists)
for i in range(0, count):
for j in range(j+1, count):
if lists[i] > lists[j]:
lists[i], lists[j] = lists[j], lists[i]
return lists
2,冒泡排序的优化
若在某一轮排序中未发现气泡位置的交换,则说明待排序的无序序列其实已经“有序”了。因此,冒泡排序可在此轮排序后终止。为此,我们增加一个标志位flag,在每轮排序前,先将其置为false,若排序过程中发生了交换,则将其置为true。各轮排序结束时检查flag,若未曾发生过交换则终止算法。
bool flag;
for (int i = 0; i < len-1; i++)
{
int temp = 0;
flag = false;
for (int j = len-1; j > i; j--) {
if (ar[j] < ar[j - 1]){
temp = ar[j];
ar[j] = ar[j - 1];
ar[j - 1] = temp;
flag = true;
}
}
if (!flag) {
break;
}
}
另一种写法
void NewBubbleSort(int a[], int n)
{
int exchange;
int temp;
int j=0;
exchange = n-1;
while( exchange ){
exchange = 0;
for( j = 0 ;j < n-1;j++ ){
if(a[j] > a[j+1] ){
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
exchange = j;
}
}
}
}
占时写到这吧,脖子好酸啊.......
标签:
原文地址:http://www.cnblogs.com/letgo/p/5830673.html