zoukankan      html  css  js  c++  java
  • 实现堆排、快排、归并

    春招的时候已经总结过这三个复杂的排序算法了,但是,当时还是有些不解,关于排序算法,冒泡,直接插入,简单选择都是很简单的,只要了解思想就可以写出来。

    这三个算是比较复杂的了。(代码已测)


    (一)快排

    快排考的是最多次的。之前看大神写的算法很简单,思想也很好。就一直用他的思想去思考快排了。

    就是挖坑法。

    拿走第一个元素作为标兵元素,即挖坑,然后从后面找一个比它小的填坑,然后又形成一个坑,再从前面找一个比标兵大的填坑,又形成一个坑。……最后一个坑填入标兵就好。

    然后就是递归了。再在标兵左边排序,右边排序。

    void QSort(int* num, int start, int end) {
        if(num == NULL||start >= end)
            return;
        int tmp = num[start];
        int i = start, j = end;
        while (i<j) {
            while (i<j&&num[j]>tmp) {
                j--;
            }
            if (i<j)
                num[i++] = num[j];
            while (i<j&&num[i]<tmp) {
                i++;
            }
            if (i<j)
                num[j--] = num[i];
        }
        num[i] = tmp;
        QSort(num, start, i - 1);
        QSort(num, i + 1, end);
    }

    归并:

    归并的思想就是分治-组合。

    先divide,然后merge。

    divide的思想比较简单,找到middle,再划分A[start,,,,,middle],A[middle+1...end]

    对于左边在递归划分,划分直至只剩一个元素,然后再merge。merge的时候需要一个临时数组。merge的时候是A[first...middle]和A[middle+1……end]合并。

    对于右边在递归划分,划分直至只剩一个元素,然后再merge。

    左边和右边都有序了,然后再将两个数组合并为一个数组。最后整个数组都有序了。(先处理左边,再处理右边)

    void merge(int* A, int start, int middle, int last, int *tmp) {
    
        int i1 = start, j1 = middle;
        int i2 = middle+1, j2 = last;
        int index = 0;
        while (i1<=j1&&i2<=j2) {
            if (A[i1]<=A[i2])
                tmp[index++] = A[i1++];
            else tmp[index++] = A[i2++];
        }
        while (i1 <= j1) {
            tmp[index++] = A[i1++];
        }
        while (i2 <= j2) {
            tmp[index++] = A[i2++];
        }
        for (int i = 0; i<index; i++) {
            A[start + i] = tmp[i];
        }
        return;
    }
    void divide(int* A, int start, int end, int* tmp) {
        if (start<end) {
            int middle = (start + end) / 2;
            divide(A, start, middle, tmp);
            divide(A, middle+1, end, tmp);
            merge(A, start, middle, end, tmp);
        }
    }
    void mergesort(int* A, int size) {
        if (A == NULL || size == 0 || size == 1)
            return;
        int* tmp = new int[size];
        divide(A, 0, size - 1, tmp);
        delete[] tmp;
        return;
    }

    堆排序:(我觉得好难啊)

    堆排序(以最大堆为例子):
    1.首先要构建一个最大堆(从size/2-1位置开始维护堆,叶子节点默认已经是一个最大堆了,维护到根节点,则已经构成一个最大堆)
    2.交换根节点(此时根节点是最大值),和最后一个节点,破坏了最大堆的性质,此时继续维护最大堆(维护最大堆的过程就是类似直接插入排序,找到维护点合适插入的位置,保证最大堆性质不被破坏就好)
    3.循环交换最后一个节点和根节点,每次维护最大堆的规模减一(找到最大,找到次大,次次大……),到最后到根节点,也就排序完成了

    void swap(int& a, int& b) {
        a ^= b;
        b ^= a;
        a ^= b;
    }
    void HeapAdjust(int* A, int size, int start) {
        int i = start;
        int j = 2 * i + 1;
        int tmp = A[i];
        while (j <= size) {
            if (j + 1 <= size&&A[j + 1]>A[j])
                j++;
            if (A[j] <= tmp)
                break;
            A[i] = A[j];
            i = j;
            j = 2 * i + 1;
        }
        A[i] = tmp;
        return;
    }
    
    void CreateHeap(int* A, int size) {
        for (int i = size / 2 - 1; i >= 0; i--)
            HeapAdjust(A, size - 1, i);
    }
    
    void HeapSort(int* A, int size) {
        if (A == NULL || size == 0 || size == 1)
            return;
        CreateHeap(A, size);
        for (int i = size - 1; i >= 1;) {
            swap(A[0], A[i--]);
            HeapAdjust(A, i, 0);
        }
    }
  • 相关阅读:
    ubuntu14.04 Cannot find OpenSSL's <evp.h>
    git 常用命令
    Python3常用模块的安装
    Centos7 安装配置优化mysql(mariadb分支)
    Centos7 编译安装python3
    Centos6.5搭建git远程仓库
    年轻
    springboot 报错Field XXX required a bean of type XXX that could not be found.
    springboot 启动报错[classpath:/application.yml] but snakeyaml was not found on the classpath
    idea 使用点击maven clean/install或maven其他命令失败,显示:乱码+archetypeCatalog=internal
  • 原文地址:https://www.cnblogs.com/LUO77/p/5798149.html
Copyright © 2011-2022 走看看