概念一:排序算法是否是稳定的
给定序列{3,15,8,8,6,9}
若排序后得到{3,6,8,8,9,15}, 则该排序算法是不稳定的,原本后面的8(加粗)现在位于前面了。
概念二: 内部排序、外部排序
内部排序是指将待排序的数据存放在内存中进行排序的过程。
外部排序是指待排序的数据很多,以致内存一次不能容纳所有数据,在排序过程中需要对外存进行访问的排序过程。
概念三:评价标准
排序过程中最基本的操作是关键字的比较和数据的移动,因此以关键字比较次数和数据的移动次数来度量排序算法的时间复杂度。
插入排序
一、直接插入排序:
遍历到第i个元素的时候,将其与前面的元素(已有序)进行比较,放入合适的位置。
时间复杂度 O ( n 2 ) O(n^2) O(n2)
排序算法是稳定的
#include <iostream>
using namespace std;
void InsertionSort(int data[],int n){
int tmp,i,j;
for( i=1;i<n;i++){
tmp = data[i];
for( j=i-1;j>=0;j--){
if(data[j]>tmp){
data[j+1]=data[j];
}else{
break;
}
}
data[j+1] = tmp;
}
}
int main(){
int data[6] = {32,18,65,48,27,9};
InsertionSort(data,6);
for(int i=0;i<6;i++)
cout<<data[i]<<endl;
return 0;
}
二、折半插入排序
上面提到的直接插入排序,当遍历到第i个元素的时候,它前面的所有元素都已经排好序了,因此可以使用二分法来确定第i个元素的位置。这就是折半插入排序。
时间复杂度 O ( n 2 ) O(n^2) O(n2)
排序算法是稳定的
#include <iostream>
using namespace std;
void BinaryInsertionSort(int data [], int n){
int tmp,left,right,mid;
for(int i = 1; i< n; i++){
tmp = data[i];
left = 0;
right = i-1;
// 二分法确定当前元素要位于什么位置
while(left <= right){ // 需仔细考虑这里,因为当前元素可能要位于的位置就是当前位置
mid = (left + right)/2;
if(data[mid] > tmp)
right = mid-1;
else
left = mid+1;
}
// 确定好位置后,进行移动
for(int j=i-1;j>=left;j--){
data[j+1]=data[j];
}
data[left]=tmp;
}
}
int main(){
int data[6] = {32,18,65,48,27,9};
BinaryInsertionSort(data,6);
for(int i=0;i<6;i++)
cout<<data[i]<<endl;
return 0;
}
三、希尔排序
希尔排序是直接插入排序改良的算法,思想是:先将待排序数据序列划分成若干个子序列分别进行直接插入排序;待整个序列基本有序后,再对全部数据进行一次直接插入排序。
希尔排序步长从大到小调整,后面元素逐个和前面元素按间隔步长进行比较并交换,直至步长为1,步长选择是关键。
希尔排序算法复杂度依赖于增量序列的选择,但是大致是 O