选择排序

来源:互联网 发布:计时器软件哪个好 编辑:程序博客网 时间:2024/06/03 14:06
  • 简单选择排序
  • 堆排序

简单选择排序

原理非常简单

n 个元素的数组,i = 1,2,3,…
n-i+1 个元素中选出最大(小)的元素
与第 i个元素交换

当然简单的方法效率不是很理想,很容易看出简单选择排序的时间复杂度为 O(n2)

我的代码如下

public static void sort(int[] data){        int len = data.length;        for(int i = 0; i < len; i ++){            int min = i;            for(int j = i; j < len; j ++){                if(data[j] < data[min] ){                    min = j;                }            }            if(i != min){                int temp = data[i];                data[i] = data[min];                data[min] = temp;            }        }    }

堆排序

首先介绍一下 的概念,

n个元素的序列 , , 当且仅当满足以下关系时,称之为堆

{kik2ikik2i+1()

{kik2ikik2i+1()

其中
(i=1,2,,n2)

这个定义放在一个一维数组上是不好理解的,如果我们把这样的序列看成一颗 完全二叉树 就好理解的多了。

完全二叉树中的所有非叶子结点的值均不大于(不小于)其左、右孩子结点的值。
如图:

堆的完全二叉树表示

由图可知堆顶元素( 树的根结点)是序列的最大(最小)值。
堆排序就是利用了堆的这一特点。
原理如下

n 个元素的数组,i = 1,2,3,…
将数组构造成堆
输出堆顶元素
调整剩余 n - i 个元素构建成堆

问题在于
(1)怎样将无序数组建成堆
(2)怎样调整剩余元素成新堆

调整剩余元素成新堆

大家应该都会觉得第二个问题简单一些,因为剩余元素即左右子树,已经是堆。
堆排序中,当输出堆顶元素后,以最后一个元素代替成为堆顶。仅需自顶而下的比较、调整就能生成新的堆。
如图
这里写图片描述

将无序数组建成堆

如果上一步调整的操作叫做 “筛选”,那么将无序数组建成堆的过程就是重复 “筛选”的过程,我们从第一个非叶子结点(在完全二叉树中 是第n2 个元素)开始向对所有非叶子结点执行“筛选”。
如图

这里写图片描述

堆排序的时间复杂度

容易看出每次“筛选”的时间复杂度是O(lgn)。而完成排序至少执行 n1次“筛选”。所义堆排序的时间复杂度为O(nlgn)

我的代码下

/**     * 堆排序     * @param data 待排序数组     */    public static void sort(int[] data){        buildMaxHeap(data);        int temp = 0;        int size = data.length;        for(int i = data.length - 1; i > 1; i --){            temp = data[i];            data[i] = data[1];            data[1] = temp;            size --;            maxHeapify(data,1,size);        }    }    /**     * 初次构建堆     * @param data 待排序数组     */    public static void buildMaxHeap(int[] data){        int len = (data.length-1) / 2;        int size = data.length;        for(int i = len; i > 0; i --){            maxHeapify(data,i,size);        }    }    /**     * "筛选" 操作     * @param data 待排序数组     * @param i    堆顶元素的索引     * @param size 堆的大小     */    public static void maxHeapify(int[] data, int i,int size){        int l = left(i);        int r = right(i);        int largest = 0;        if(l< size && data[l] > data[i]){            largest = l;        }else{            largest = i;        }        if( r < size && data[r] > data[largest]){            largest = r;        }        if(largest != i){            int temp = data[i];            data[i] = data[largest];            data[largest] = temp;            maxHeapify(data,largest,size);        }    }    /**     * 得到左孩子     * @param i 父结点索引     * @return 左孩子结点索引     */    public static int left(int i){        return i*2;    }    /**     * 得到右孩子     * @param i 父结点索引     * @return 右孩子结点索引     */    public static int right(int i){        return i * 2 + 1;    }

[1] 严蔚敏 . 数据结构(c语言版)
[2] 算法导论

0 0
原创粉丝点击