一、插入排序
1.1直接插入排序
void InsertSort(int array[], int n)
{
int i, j;
int current;
for(i = 1; i < n; ++i)//初始默认array[0]为已排好序的序列
current = array[i];//指向当前正在排序的元素
for(j = i-1; current < array[j] && j >= 0; j--) //在array[0...i-1]中逆序比较(j>=0不可省略,当插入元素最小时用来跳出当前for循环)
array[j+1] = array[j];//若该处不是新元素插入位置,则数组元素依次后移
array[j+1] = current;
};
1.2折半插入排序
void InsertSort(int A[], int n)
{
int i, j, low, high, mid;
int current;
for(int i = 1; i < n; ++i){//依次将A[1]~A[n-1]插入到前面的已排序序列。默认A[0]为有序序列
current = A[i];//当前排序元素
low = 0; high = i-1; //折半查找范围:A[0...i-1]
//1.折半寻找插入位置
while(low <= high){
mid = (low + high) / 2;
if(current < A[mid] ) high = mid - 1;//查找左半子表
else low = mid + 1;//查找右半子表
}
//2.后移元素,空出插入位置(插入位置下标为low或high+1)
for(j = i-1; j >= low; j--){
A[j+1] = A[j];
}
//3.插入元素 (此时low=high+1)
A[low] = current;
}
};
与直接插入排序相比,减少了元素的比较次数。每次循环,都是先找到插入位置,再来移动元素,而不是比较一次移动一个元素。
一次循环比较log(n)次,则n次循环比较nlog(n)次。一次循环移动1~n次,则n次循环移动n平方次。
二、交换排序
2.1冒泡排序
void swap(int &a, int &b){
int temp = a;
a = b;
b = temp;
return;
}
void InsertSort(int A[], int n)
{
bool flag;
for(int i = 0; i < n; ++i){//一趟冒泡排序
flag = false;//本趟循环是否发生交换的标志
for(int j = n-1; j > i; --j){//从后往前冒泡
if(A[j] < A[j-1]){//若为逆序
swap(A[j], A[j-1]);
flag = true;
}
}
if(flag == false){//若该趟循环未进行元素交换,则已有序
return;
}
}
};
2.2快速排序
int Partition(int A[], int low, int high){
int pivot = A[low];//将第一个值设为哨兵,来对序列进行划分。
while(low < high){
while(low < high && A[high] >= pivot) high--;//右指针移动
A[low] = A[high];
while(low < high && A[low] <= pivot) low++;//左指针移动
A[high] = A[low];
}
A[low] = pivot;//哨兵元素的最终存放位置
return low;
}
void QuickSort(int A[], int low, int high) {
if(low < high){
int pivotpos = Partition(A,low,high);//返回第一个元素的最终位置
QuickSort(A, low, pivotpos-1);
QuickSort(A,pivotpos+1, high);
}
};