前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >几种排序算法

几种排序算法

作者头像
earthchen
发布2020-09-24 11:32:39
2670
发布2020-09-24 11:32:39
举报
文章被收录于专栏:earthchen的专栏earthchen的专栏

并归排序

代码语言:javascript
复制
public class MergeSort {


    private static void merge(int a[], int first, int mid, int last) {
        int i = first;
        int j = mid + 1;
        int m = mid;
        int n = last;
        int k = 0;
        // 临时数组保存
        int[] temp = new int[last + 1];
        // 两个数组的左边小于左边 右边小于右边的情况下
        while (i <= m && j <= n) {
            if (a[i] <= a[j]) {
                temp[k++] = a[i++];
            } else {
                temp[k++] = a[j++];
            }
        }
        // 把左边数组或者右边的数组剩下的元素直接添加到临时数组中
        while (i <= m) {
            temp[k++] = a[i++];
        }
        while (j <= n) {
            temp[k++] = a[j++];
        }
        // 赋值给原始数组
        for (i = 0; i < k; i++) {
            a[first + i] = temp[i];
        }
    }


    /**
     * 递归 排序
     *
     * @param a
     * @param first
     * @param last
     */
    private static void mergeSort(int a[], int first, int last) {
        if (first < last && a.length > 1) {
            // 求中位数
            int mid = (first + last) / 2;
            // 左边有序
            mergeSort(a, first, mid);
            // 右边有序
            mergeSort(a, mid + 1, last);
            merge(a, first, mid, last);
        }
    }


    public static void main(String[] args) {
        int[] a = {1, 3, 5, 2, 4, 6, 7, 8};
        mergeSort(a, 0, 7);
        System.out.println(Arrays.toString(a));
    }
}

堆排序

堆节点的访问

通常堆是通过一维数组来实现的。在阵列起始位置为0的情况中 (1)父节点i的左子节点在位置(2i+1); (2)父节点i的右子节点在位置(2i+2); (3)子节点i的父节点在位置floor((i-1)/2);

堆操作

堆可以分为大根堆和小根堆,这里用最大堆的情况来定义操作:

  • 最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点。这是核心步骤,在建堆和堆排序都会用到。比较i的根节点和与其所对应i的孩子节点的值。当i根节点的值比左孩子节点的值要小的时候,就把i根节点和左孩子节点所对应的值交换,当i根节点的值比右孩子的节点所对应的值要小的时候,就把i根节点和右孩子节点所对应的值交换。然后再调用堆调整这个过程,可见这是一个递归的过程。
  • 建立最大堆:将堆所有数据重新排序。建堆的过程其实就是不断做最大堆调整的过程,从len/2出开始调整,一直比到第一个节点。
  • 堆排序:移除位在第一个数据的根节点,并做最大堆调整的递归运算。堆排序是利用建堆和堆调整来进行的。首先先建堆,然后将堆的根节点选出与最后一个节点进行交换,然后将前面len-1个节点继续做堆调整的过程。直到将所有的节点取出,对于n个数我们只需要做n-1次操作。

代码

代码语言:javascript
复制
def max_head(mylist, headsize, root_index):
    # 计算左右子节点索引
    left = root_index*2+1
    right = root_index*2+2
    large_index = root_index
    # 判断左节点的值是否大于父节点
    if left < headsize and mylist[left] > mylist[large_index]:
        large_index = left
    # 判断右节点的值是否大于父节点
    if right < headsize and mylist[right] > mylist[large_index]:
        large_index = right
    #如果做了堆调整则larger的值等于左节点或者右节点的,这个时候做对调值操作
    if large_index != root_index:
        mylist[large_index], mylist[root_index] = mylist[root_index], mylist[large_index]
        max_head(mylist, headsize, large_index)


def create_head(mylist):
    length = len(mylist)
    max_child_index = (length - 2)//2
    #从后往前出数
    for i in range(max_child_index, -1, -1):
        max_head(mylist, length, i)


def sort_head(mylist):
    """
    将根节点取出与最后一位做对调,对前面len-1个节点继续进行对调整过程。
    """
    create_head(mylist)
    for i in range(len(mylist)-1, -1, -1):
        mylist[0], mylist[i] = mylist[i], mylist[0]
        max_head(mylist, i, 0)


if __name__ == "__main__":
    mylist = [49, 38, 65, 97, 76, 13, 27, 49]
    sort_head(mylist)
    print(mylist)

top k问题

快速排序求解

由于快速排序的思路是找到一个基准值,然后将大于该值得放在右边,小于该值得放在左边

如果此时这个基准值刚好是第k的数,那边左边就是最小的k个数,右边则是最大的k个数

此处以最小的k个数为例

如果当前的基准值不到左边的数不到k个,那么就需要在右边大于基准值的部分选取缺少的个数

如果当前基准值左边的数量大于k个,那么就需要在左边的部分中在选取k个数

直到刚好获取到第k个数

代码

代码语言:javascript
复制
public class TopK {


    /**
     * 快速排序
     *
     * @param a
     * @param start
     * @param end
     * @return
     */
    public static int quickSort(int a[], int start, int end) {
        if (start >= end || a.length <= 1) {
            return -1;
        }
        int i = start;
        int j = end;
        int x = a[i];
        while (i < j) {
            while (i < j && a[j] >= x) {
                j--;
            }
            if (i < j) {
                a[i] = a[j];
                i++;
            }

            while (i < j && a[i] < x) {
                i++;
            }
            if (i < j) {
                a[j] = a[i];
                j--;
            }
        }
        a[i] = x;
//        quickSort(a, start, i - 1);
//        quickSort(a, i + 1, end);
        return i;
    }

    /**
     * 选取第k个数
     *
     * @param arr
     * @param start
     * @param end
     * @param k
     */
    public static int selectK(int arr[], int start, int end, int k) {
        if (start > end || k < 1) {
            return -1;
        }
        if (start == end) {
            return arr[start];
        }
        int temp = quickSort(arr, start, end);
        // 当前左边刚好有k个数(小于基准值)
        if (start + k == temp + 1) {
            return arr[temp];
            // 左边小于基准值得个数大于k
        } else if (start + k < temp + 1) {
            return selectK(arr, start, temp - 1, k);
            // 左边小于基准值得个数小于k(从右边在获取缺少的数量)
        } else {
            return selectK(arr, temp + 1, end, k - (temp - start + 1));
        }
    }


    public static void main(String[] args) {
        int k = 4;
        int a[] = {2, 0, 5, 4, 7, 3, 1};
        System.out.println("第k个数为:" + TopK.selectK(a, 0, a.length - 1, k));
//        quickSort(a, 0, a.length - 1);
        for (int i : a) {
            System.out.println(i);
        }
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-11-28,,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 并归排序
  • 堆排序
    • 堆节点的访问
      • 堆操作
        • 代码
        • top k问题
          • 快速排序求解
            • 代码
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档