折半插入
// 折半插入
void BinSort(int a[], int n){
for(int i = 2; i <= n; i ++){
int x = a[i];
// 查找待插入元素
int mid;
int low = 1, high = i - 1;
while(low <= high){
mid = (low + high) / 2;
if(a[i] == mid) break;
else if(a[i] < mid) high = mid - 1;
else low = mid + 1;
}
for(int j = i - 1; j>= low; j --) a[j + 1] = a[j]; // 向前移动元素
a[low] = x;
}
}
选择排序(链表)
// 选择排序(链表)
LinkList* SelectSort(ListNode *head){
if(head == NULL) return head;
Node *p;
for(p = head->next; p != NULL; p = p->next){
Node *q ; // 遍历指针(往后查找最小的值)
Node *Min == NULL; // 用来保存最小的结点
// 从p结点开始往后查找最小的值
for(q = p->next;q != NULL; q = q->next){
if(q->data < s->data) Min = q;
}
if(Min == NULL) continue;
// 交换两者的值
int x = p->data;
p->data = Min->data;
Min->data = p->data;
}
return head; // 返回链表
}
快速排序
// 快速排序 平均时间复杂度 O(nlog2n) 空间复杂度 O(log2n) (递归栈)
int Partition(int a[], int low, int high){ // 一次划分
int x = a[low]; // 选择基准记录
while(low < high){
while(a[high] >= x && low < high) high --; // 找到比枢轴小的元素
if(low < high) a[low] = a[high], low ++; // 将其送入"空"单元 并且low指针加一
while(a[low] <= x && low < high) low ++; // 找到比枢轴大的元素
if(low < high) a[high] = a[low], high --; // 将其送入“空”单元,并且high指针加一
}
a[low] = x; // 最后将枢轴送入“空单元”
return low; // 返回枢轴的下标
}
void QuickSort(int a[], int low, int high){
if(low < high){
int pos = Partition(a, low, high); // 进行一次划分
QuickSort(a, low, pos - 1); // 对左子表进行快速排序
QuickSort(a, pos + 1, high); // 对右子表进行快速排序
}
}
堆排序
// 堆排序 时间复杂度 O(nlog2n) 空间复杂度 O(1)
void HeapReBuild(int a[], int k, int m){ // 堆的重建
// 重建堆,k是最上面的根的下标,m是完全二叉树最后一个下标
int root = a[k]; // 保存根记录
int i = k, j = 2 * k ; // i是根结点下标,j是根节点的左子树下标
bool flag = false; // 循环退出的标志变量
while(j < m && !flag){
if(j + 1 < m && a[j] < a[j + 1]) j = j + 1; // 如果存在右子树且右子树大的话,j右移一位指向右子树
if(root >= a[j]) flag = true; // 根结点已经满足大根堆条件 直接退出
else{
a[i] = a[j];
i = j; // 使用i保留当前子树的下标
j = 2 * i; // j继续往子树寻找比root大的结点
}
}
a[i] = root; // 最后i空出的位置就是原根节点插入的位置
}
void HeapCreate(int a[], int n){ // 构造初始堆
for(int i = n / 2; i >= 1; i --){ // 从最后一个叶节点的双亲结点开始直到根节点
HeapReBuild(a, i, n); // 根是i,最后一个元素是n
}
}
void HeapSort(int a[], int n){ // 堆排序
HeapCreate(a, n); // 首先构造初始堆
for(int i = n; i >= 2; i --){ // 从最后一个元素开始调整
// 堆顶和堆尾呼唤
int b = a[1];
a[1] = a[i];
a[i] = b;
HeapReBuild(a, 1, i - 1); // 堆的重建 从根结点开始调整,最后元素是i-1
}
}
归并排序
// 归并排序 时间复杂度 O(nlog2n) 空间复杂度 O(n) 主要在归并数组用到
void Merge(int a[], int low, int mid, int high){ // 把两个有序表合成一个的抄过来即可
int *A = (int *)malloc(sizeof(int) * (high - low + 1) ); // 新建存储单元
int i = low, j = mid + 1; // 分别遍历左表和右表
int k = 0; // 新数组A的下标
while((i <= mid) && (j <= high)){
if(a[i] <= a[j]) A[k++] = a[i++]; // 在等于的情况下,优先放左边的 保证稳定性
else A[k++] = a[j++];
}
// 对剩下没有遍历到的元素进行赋值
while(i <= mid) A[k++] = a[i++];
while(j <= high) A[k++] = a[i++];
// 将合并好的元素放回原表
k = 0, i = low;
while(i<=high) a[i++] = A[k++];
free(A);
}
void MergeSort(int a[], int low, int high){
int mid;
while(low < high){
mid = (low + high) / 2;
MergeSort(a, low, mid); // 对前半段归并排序
MergeSort(a, mid + 1, high); // 对后半段归并排序
Merge(a, low, mid, high); // 排序好的两段合并
}
}x