直接插入排序
从第二个元素开始,每次选择一个元素插入到之前已经排好序的部分。
选择插入位置的时候从后往前,将带插入元素取出,依次后移大于带插入元素的数。
算法复杂度:
最好是正序有序,需要n次比较。
最差逆序有序,复杂度O(n2)
平均复杂度O(n2)
插入排序是稳定的
void insertsort(int a[],int size){
int tmp;
for(int i = 1; i < size; ++i){
tmp = a[i];
int j = i-1;
while(j>=0&&a[j]>a[i]){
a[j+1] = a[j];
j--;
}
a[j+1] = tmp; //最后j位置数小于带插入的数,在j+1位置插入数
}
}
希尔排序
实际也是一组插入排序,只不过是分组插入排序。给定增量值d,将序列分为d个子序列,先插入排序子序列,最后对全部序列进行 一次插入排序。
也就是增量值必须取小于n的值,且最后一个增量必须为1。
由于大于1的增量,排序是不稳定的。
平均复杂度:O(nlogn)
void shellsort(int a[],int size){
int d,i,j;
int tmp; //暂存数据
d = n/2;
while(d>0){
for(i = d; i < size; ++i){
j = i-d;
tmp = a[i];
while(j>=0 && a[j] > tmp){
a[j+d] = a[j];
j -= d;
}
a[j+d] = tmp;
}
d /= 2;
}
}
快速排序
对冒泡排序的一种改进,基于交换
算法复杂度在最坏情况下为O(n2),平均为O(nlogn)
同时快排是不稳定的
void quicsort(int a[],int low,int high){
if(low>=high) return;
int i = low, j = high;
int tmp = a[i];
while(i<j){
while(i<j && a[j] > tmp) j--;
if(i<j) a[i++] = a[j];
while(i<j && a[i] < tmp) i++;
if(i<j) a[j--] = a[i];
}
a[i] = tmp;
quicksort(a,low,i-1);
quicksort(a,i+1,high);
}
选择排序
排序不稳定
void selectsort(int a[],int size){
int tmp,k;
for(int i = 0; i < size-1; ++i){
tmp = a[i];
k = i;
for(int j = i+1; j < size; ++j){
if(a[j] < tmp){
tmp = a[j];
k = j;
}
}
if(k != i) swap(a[i],a[k]);
}
}
堆排序
- 在数组中建堆
- 从最后一个非叶节点进行调整
- 将堆顶元素与最后的元素交换,然后调整堆。
复杂度为:O(nlogn)
void heapAdjust(int a[],int i,int size){
int tmpMin = a[i];
for(int j = i*2+1; j < size; j = j*2+1){
if(j<size-1&&a[j+1]<a[j]) j += 1;
if(a[i] < a[j]) break;
a[i] = a[j];
i = j;
}
}
void buildHeap(int a[],int size){
for(int i = size/2+1; i >= 0; --i){
heapAdjust(a,i,size);
}
}
void heapsort(int a[],int size){
buildHeap(a,size);
for(int i = size-1; i > 0; --i){
swap(a[0],a[i]);
heapAdjust(a,0,i);
}
}
归并排序
归并排序是稳定排序,复杂度为O(nlogn),缺点是需要额外的O(n)空间
void merge(int a[], int tmp[],int left,int mid, int right) {
int i = left, j = mid+1;
int k = i;
while (i <= mid && j <= right) {
if (a[i] < a[j]) {
tmp[k++] = a[i++];
}
else {
tmp[k++] = a[j++];
}
}
while (i <= mid) tmp[k++] = a[i++];
while (j <= right) tmp[k++] = a[j++];
for (int p = left; p <= right; p++) {
a[p] = tmp[p];
}
}
void m_sort(int a[],int tmp[],int left,int right) {
if (left == right) return;
int mid = (left + right) / 2;
m_sort(a, tmp,left, mid);
m_sort(a,tmp, mid + 1, right);
merge(a, tmp,left, mid,right);
}
void mergesort(int a[], int size) {
int *tmp = new int[size];
m_sort(a, tmp, 0, size - 1);
delete[]tmp;
}