一、冒泡排序
时间复杂度:O(n^2)
额外空间复杂度:O(1)
void swap(int arr[], int a, int b){
int tmp = a;
arr[a] = arr[b];
arr[b] = tmp;
}
//首先判断数组是否需要排序
if(arr.size() < 2 || arr == null)
return;
for(int end = arr.size()-1; end > 0; end--){
for(int i = 0; i < end; i++){
if(arr[i] > arr[i+1])
swap(arr, i, i +1);
}
}
二、插入排序
时间复杂度:O(n^2)
额外空间复杂度:O(1)
设数组有N个元素,则第一个元素一定自己有序;
把2到N位置的元素有序插到已经有序的数列上
void Insertion_sort(Element arr[], int N){
if(N < 2) return;
for(int i = 1; i < N; i++){
int tmp = arr[i];//待插入值
for(int j = i; j > 0 && arr[j-1] > tmp; j--)//若待插入值的前一个元素大于自身,则前一个元素往后移一个位置
arr[j] = arr[j-1];
arr[j] = tmp;//待插入值最终位置
}
}
三、选择排序
时间复杂度:O(n^2)
额外空间复杂度:O(1)
将未排序数组中最小值放到有序数列的最后
void swap(int arr[], int a, int b){
int tmp = a;
arr[a] = arr[b];
arr[b] = tmp;
}
void Selection_sort(Element arr[], int N){
for(int i = 0; i < N; i++){
int minsub = i;
for(int j = i+1; j < N; j++)
minsub = arr[j] > arr[minsub] ? minsub : j;
swap(arr, minsub, i);
}
}
四、归并排序
时间复杂度O(N*logN);
额外空间复杂度O(N);
递归解法
void Merge(int A[], int tmpA[], int L, int R, int RightEnd){
int LeftRight = L + (RightEnd - L) >> 1;
int tmp = L, N = RightEnd - L + 1;
while(L <= LeftEnd && R <= RightEnd){
if(A[L] < A[R]) tmpA[tmp++] = A[L++];
else tmpA[tmp++] = A[R++];
}
while(L <= LeftEnd) tmpA[tmp++] = A[L++];
while(R <= RightEnd) tmpA[tmp++] = A[R++];
for(int i = 0; i < N; i++)
A[i] = tmpA[i];
}
void Msort(int A[], int tmpA[], int L, int RightEnd){
int center;
if(L < RightEnd){
center = L + (Right - L) >> 1;
Msort(int A[], int tmpA[], int L, int center);
Msort(int A[], int tmpA[], int center+1, int RightEnd);
Merge(int A[], int tmpA[], int L, int center+1, int RightEnd);
}
}
void Merge_sort(int A[], int N){
if(N < 2) return;
int *tmpA = malloc(N * sizeof(int));
Msort(A, tmpA, 0, N-1);
free(tmpA);
}
非递归解法(步长问题)
void mergesort(int A[], int N){
for(int step = 2; step / 2 < N; step *= 2){
for(int i = 1; i <= N; i += step){
int mid = i + step/2 -1;
if(mid <= N)
Merge(A, i, mid, mid+1, min(i+step-1, n));
}
}
}
五、快速排序
int cutoff;
void Quicksort(Element A[], int L, int R){
if(R-L < cutoff)//规模小就用别的排序
{
for(; ;){
while(A[i++] < mid); //mid是主元,取数组的头尾中的元素中位数
while(A[j--] > mid);
if(i < j)
swap(A[i], A[]j);
else//i > j就越界了
break;
}
swap(A[i], A[R-1]);
//此时,mid左边的元素都比mid小
//以下递归实现
Quicksort(A, L, i-1);
Quicksort(A, i+1, R);
}
else Insertsort(A, int R-L+1)
}
六、堆排序
借助完全二叉树思想,数组存储
//最大堆的建立
typedef struct HeapStruct *MaxHeap;
struct HeapStruct{
ElementType *Elements;
int size;
int maxsize;
};
MaxHeap Creat(int N){
MaxHeap H = malloc(sizeof(HeapStruct));
H->Elements = malloc((N + 1) * sizeof(ElementType));
H->maxsize = N;
H->Elements[0] = MAX;//很大的值,比任何潜在的元素都大,哨兵
return H;
}
//插入节点
void Insert(MaxHeap H, ElementType item){
//判断最大堆是否已经满了
int i;//i表示最大堆插入元素后 最后的位置
if(H->size == H->maxsize) return;
i = ++H->size;
//调整堆,使其变成最大堆,新插入的元素与父节点相比
for(;H->Elements[i/2] < item; i /= 2)
H->Elements[i] = H->Elements[i/2];
H->Elements[i] = item;
}
//删除根节点(交换根节点和最后节点,然后调整堆)
ElementType DeleteMax(MaxHeap H){
//判断是否为空
if(H->size == 0) return ;
int parent, child, max = H->Elements[1];
int temp = H->Elements[H->size];
H->Elements[H->size--] = max;//把最大值放在数组最后
//调整堆
for(parent = 1; parent*2 <= H->size; parent = child){
child = parent*2;//左孩子
//找左右孩子中较大的那个
if((child != H->size) && child < Elements[child+1])
child++;
if(temp >= H->Elements[child]) break;
H->Elements[parent] = H->Elements[child];
}
H->Elements[parent] = temp;
}
//对上段代码进行size次循环即是堆排序
七、桶排序
普通版:
假设我们有N个学生,他们的成绩在0到100之间(于是又101个不同的成绩值)。
我们建立101个桶(容器)分别存放相同成绩的人;
比如
void Bucket_sort(ElementType arr[], int N){
count[];//初始化
while(每一个学生的成绩){
将该学生插入到成绩所对应的桶中
}
for(int i = 0; i <= 100; i++)
if(count[i])
输出整个count[i]链表;
}
(一)计数排序
加入有一组待排序列,以及数据范围为[0, 200];
则我们建立长为200-0+1的整形数组,int count[201];
遍历所有数据,分别放到对应的桶中,然后顺序倒出;
while(cin >> num)
count[num]++;
for(int i = 0; i < N; i++)
if(count[i])
cout << count[i];
上述排序,只适用于数据大小很集中的情况,类似0,1,2,999,10,5,6…等等就不适合了。
那我们该怎么办呢?看下面的基数排序;
升级版(二)基数排序