选择排序

选择排序

基本思想:

每一趟 (例如第 i 趟, i = 0, 1, …, n-2) 在后面 n-i 个待排序元素中选出排序码最小的元素,作为有序元素序列的第 i 个元素。待到第 n-2 趟作完,待排序元素只剩下1个, 就不用再选了。

主要的选择排序算法:

  1. 直接选择排序
  2. 堆排序

直接选择排序

基本步骤

  1. 在一组元素 V[i]~V[n-1] 中选择具有最小排序码的元素;
  2. 若它不是这组元素中的第一个元素, 则将它与这组元素中的第一个元素对调;
  3. 在这组元素中剔除这个具有最小排序码的元素。在剩下的元素V[i+1] ~ V[n-1]中重复执行第①、②步, 直到剩余元素只有一个为止。

复杂度和稳定性

时间复杂度:O(n2)

空间复杂度:O(1)

稳定性:不稳定

代码

public static void selectSort(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            int k = i;
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[j] < nums[k]) {
                    k = j;
                }
            }
            if (k != i) {
                int tmp = nums[k];
                nums[k] = nums[i];
                nums[i] = tmp;
            }
        }
    }

时间复杂度:O(n2)

空间复杂度:O(1)

堆排序

堆的定义

​ 设有n个数据元素的值为(k0,k1,…,kn-1),如果它们满足以下的关系:ki≤k2i+1且ki≤k2i+2(或ki≥k2i+1且ki≥k2i+2)(i=0,1,…, n-2/2 ),则称之为堆(Heap)。

​ 如果将此数据元素序列用一维数组存储,并将此数组对应一棵完全二叉树,则堆的含义可以理解为:在完全二叉树中任何非终端节点的值均不大于(或小于)其左、右孩子节点的值。

步骤

  1. 将要排序的n个元素初始化为一个最小堆;
  2. 每次从堆中提取堆顶(即删除最小)元素;
  3. 各元素将按非递减次序排列;

复杂度和稳定性

时间复杂度:O(nlog2n)

空间复杂度:O(n)

稳定性:不稳定

代码

最小堆代码

import java.util.ArrayList;
import java.util.List;

public class MinHeap {
    MinHeap() {
    }

    MinHeap(int[] items) {
        for (int i : items)
            heap.add(i);
        int pos = (items.length - 2) / 2;
        while (pos >= 0) {
            siftDown(pos);
            pos--;
        }
    }

    void add(int[] items) {
        for (int i : items) {
            insert(i);
        }
    }

    void insert(int item) {
        heap.add(item);
        siftUp(heap.size() - 1);
    }

    int top() {
        return heap.get(0);
    }

    int removeTop() {
        int top = top();
        int last = heap.remove(heap.size() - 1);
        if (!empty()) {
            heap.set(0, last);
            siftDown(0);
        }
        return top;
    }

    boolean empty() {
        return heap.size() == 0;
    }

    List<Integer> heap = new ArrayList<Integer>();

    void siftUp(int index) {
        int child = index;
        int parent = (child - 1) / 2;
        int tmp = heap.get(child);
        while (child != 0) {
            if (heap.get(parent) <= tmp)
                break;
            else {
                heap.set(child, heap.get(parent));
                child = parent;
                parent = (child - 1) / 2;
            }
        }
    }

    void siftDown(int index) {
        int parent = index;
        int child = index * 2 + 1;
        int tmp = heap.get(parent);
        while (child < heap.size()) {
            if (child < heap.size() - 1 && heap.get(child) > heap.get(child + 1))
                child++;
            if (heap.get(child) >= tmp)
                break;
            else {
                heap.set(parent, heap.get(child));
                parent = child;
                child = 2 * child + 1;
            }
        }
        heap.set(parent, tmp);
    }
}

排序代码

static void heapSort(int[] nums){
        MinHeap heap = new MinHeap(nums);
        for (int i = 0; i < nums.length; i++){
            nums[i] = heap.removeTop();
        }
    }
posted @ 2020-04-04 20:14  心流flux  阅读(198)  评论(0)    收藏  举报