数据结构排序算法笔记

数据结构

插入排序

直接插入排序

前i-1项有序,每次将L(i)插入已有序的子序列
zhijie

不带哨兵:

void InsertSort(int A[], int n) {
    int i, j, temp;
    for(i = 1; i < n; i++) {
        temp = A[i];
        for(j = i - 1; j >= 0 && temp < A[j]; j--) { //找到待插入的位置
            A[j + 1] = A[j]; //后移
        }
        A[j + 1] = temp;
    }
}

带哨兵: (用a[0]作为中间变量,减少判断) 数据从a[1]开始存储

void InsertSort2(int A[], int n) {
    int i, j;
    for(i = 2; i < n; i++) {
        A[0] = A[i];
        for(j = i - 1; A[0] < A[j]; j--) {
            A[j + 1] = A[j];
        }
        A[j + 1] = A[0];
    }
}

折半插入排序

整体思想与直接插入排序类似,在找a[i]要插入的位置时候用折半查找,更快

void InsertSort3(int A[], int n) {
    int i, j, low, high, mid;
    for(i = 2; i <= n; i++) {
        A[0] = A[i];
        low = 1;high = i - 1;
        while (low<=high){
            mid = (low + high) / 2;
            if(A[mid]>A[0]) high = mid - 1;
            else low = mid + 1;
        }
        for(j = i - 1; j >= high+1; j--) {
            A[j + 1] = A[j];
        }
        A[high + 1] = A[0];
    }
}

希尔排序

先把待排序表分成若干的形如L(i,i+d,i+2d,…,i+kd)的子表,对子表进行直接插入排序,然后改变间隔d的大小(变小)再进行直接排序
在这里插入图片描述

void ShellSort(int A[], int n) {
    int i, j, d;
    for (d = n / 2; d > 0; d /= 2){
        for (i = d+1; i <= n; ++i) {
            if(A[i]<A[i-d]){
                A[0] = A[i];
                for (j = i - d; j >= 0 && A[0] < A[j]; j -= d) {
                    A[j + d] = A[j];
                }
                A[j + d] = A[0];
            }
        }
    }
}

交换排序

冒泡排序

两两比较将,每次将第i大(小)的元素放到正确的位置

每一趟都有一个元素在正确位置上

在这里插入图片描述

void BubbleSort(int A[], int n) {
    for (int i = 0; i < n - 1; ++i) {
        bool flag = false;
        for (int j = 0; j < n - i - 1; ++j) {
            if (A[j] > A[j + 1]) {
                swap(A[j], A[j + 1]);
                flag = true;
            }
        }
        if (flag == false){
            return;
        }
    }
}

快速排序

选取一个元素pivot作为枢轴(基准),使得L(1…k-1)中的所有元素都小于pivot,L(k+1…n)中所有元素都大于pivot,然后递归两个子表

在这里插入图片描述

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 pivopos = Partition(A, low, high);
        QuickSort(A, low,  pivopos - 1);
        QuickSort(A, pivopos + 1, high);
    }   
}

选择排序

简单选择排序

每次选择最小(大)元素,加入有序表。

第i趟,关键字最小的元素与L(i)交换

void SelectSort(int A[], int n) {
    for (int i = 0; i < n - 1; ++i) {
        int min = i;
        for (int j = i + 1; j < n; ++j) 
            if (A[min] > A[j]) min = j;
        if(min != i) swap(A[i], A[min]);  
    }
}

堆排序

大根堆:根≥左、右(小根堆≤左、右)

每次选取堆顶加入有序表,将堆最底元素放让堆顶,然后调整堆,循环。

//将以k为根的子树调整为大根堆
void HeadAdjust(int A[], int k, int len) {
    A[0] = A[k];
    for (int i = 2 * k; i <= len; i *= 2) {
        if (i < len && A[i] < A[i + 1]) ++i;
        if (A[0] >= A[i]) break;
        else {
            A[k] = A[i];
            k = i;
        }
    }
    A[k] = A[0];
}
//建立大根堆
void BuildMaxHeap(int A[], int len) {
    for (int i = len / 2; i >= 0; i--) {
        HeadAdjust(A, i, len);
    }
}
    
//堆排序
void HeapSort(int A[], int len) {
    BuildMaxHeap(A, len);
    for (int i = len ; i > 1; i--) {
        swap(A[i], A[i]);
        HeadAdjust(A, 1, i - 1);
    }
}

归并排序

每次将两个或两个以上的有序表合成一个新的有序表

在这里插入图片描述

int *B=(int *)malloc(n*sizeof(int)); //辅助数组B

void Merge(int A[], int low, int mid, int high){
    int i, j, k;
    for (k= low; k <= high; k++){
        B[k] = A[k];
    }
    for(i=low, j=mid+1, k=i; i<=mid && j<=high;k++){
        if(B[i] <= B[j]){
            A[k] = B[i++];
        }else{
            A[k] = B[j++];
        }
    }
    while (i<=mid) A[k++] = B[i++];
    while (j<=high) A[k++] = B[j++];
}
void MergeSort(int A[], int low, int high){
    if(low < high){
        int mid = (low + high) / 2;
        MergeSort(A, low, mid);
        MergeSort(A, mid+1, high);
        Merge(A, low, mid, high);
    }
}

基数排序

低位优先基数排序:

分配:先考察元素的最低位(个位),一次加入队列中

收集:把队列中的各个结点首位相连

然后考察十位、百位…

在这里插入图片描述

测试

int main() {
    int n = 10;
    // 数组从0开始
    int a[10] = { 88, 10, 23, 45, 67, 90, 12, 34, 23, 67};
    // 数组从1开始
    int b[10] = { 0, 88, 10, 23, 45, 67, 90, 12, 34, 23};
    //InsertSort(a, n);
    //InsertSort2(b, n);
    //InsertSort3(b, n);
    //ShellSort(b, n);
    //BubbleSort(b, n);
    //BubbleSort2(a, n);
    //QuickSort(a, 0, n-1);
    //SelectSort(a, n);
    //HeapSort(a, n);
    MergeSort(a, 0, n-1);
    cout << "a[]排序后的数组:" << endl;
    for(int i = 0; i < n; i++) {
        cout << a[i] << " " ;
    }
    cout << endl;
    cout << "b[]排序后的数组:" << endl;
    for(int i = 1; i < n; i++) {
        cout << b[i] << " ";
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值