选择排序

  选择排序的基本方法是:每步从带排序的元素中选出关键词最小(或最大)的元素,顺序放在已排序的元素的最后,直到全部排序完为止。这里介绍简单选择排序和堆排序。

简单选择排序

1.算法思想
  每次从无序区中挑选出一个最小的值,将其与无序区的第一个元素交换,初始有序区为空,无序区包含所有待排序元素。

2.性能分析
  简单选择排序算法的效率与初始数据的顺序无关。

这里写图片描述

3.完整代码

#include<iostream>
using namespace std;

void select_sort(int a[], int n) {
    int k,temp=0;
    //每次从无序区中选出最小的元素与无序区的第一个元素交换 
    for(int i=0;i<n;++i) {
        //k标记无序区最小元素 
        k=i;
        for(int j=i+1;j<n;++j)
            if(a[j]<a[k])
                k = j;

        if(k!=i) {
            temp = a[i];
            a[i] = a[k];
            a[k] = temp;
        }
    }
}

//输出数组
void print_array(int a[],int n) {
    for(int i=0;i<n;++i){
        cout<<a[i]<<" ";
    }
    cout<<endl;
} 

int main() {
    //简单选择排序测试数据 
    int a[] = {7,3,1,12,5,9};
    int n = 6;
    cout<<"Before sort:";
    print_array(a,n);
    cout<<"After binary insertion:";
    select_sort(a,n);
    print_array(a,n); 

    return 0; 
} 

测试结果如下:

这里写图片描述

堆排序

1.算法思想
  首先按照大根推的定义将数组调整为堆(初始建堆),交换根结点a[0]和最后一个结点a[n-1](将最大元素a[0]归位);然后将a[0]~a[n-2]重新调整为堆,交换a[0]和a[n-2];如此反复,直到交换了a[0]和a[1]。

2.算法过程
(1)维护堆的性质
  AMX-HEAPIFY是用于维护最大堆性质的重要过程。它的输入为一个数组a和一个下标i。在调用MAX-HEAPIFY的时候,我们假定根结点为LEFT(i)和RIGHT(i)的二叉树都是最大堆,但这时a[i]有可能小于其孩子,这样就违背了最大堆的性质。MAX-HEAPIFY通过让a[i]在最大堆中“逐级下降”,从而使得以下标i为根结点的字数重新遵循最大堆的性质。

//假设以index为结点的左右子树Left(index)和Right(index)都为最大堆
//这时a[index]可能小于其孩子
//maxHeapify通过让a[index]在最大堆中“逐级下降”来维持最大堆的性质 
void maxHeapify(int a[], int index) {
    int l = Left(index);
    int r = Right(index);
    int largest = 0;
    if(l<heapSize && a[l]>a[index])     
        largest = l;
    else largest = index;
    if(r<heapSize && a[r]>a[largest])
        largest = r;
    if(largest != index) {
        swap(&a[largest],&a[index]);
        maxHeapify(a,largest);
    }   
}

(2)建堆
  我们可以用自底向上的方法利用过程MAX-HEAPIFY把一个大小为n=A.length的数组a[0]~a[n-1]转换为最大堆。我们知道,每个叶子节点都可以堪称只包含一个元素的堆,通过过程BUILD-MAX-HEAP对树中非叶子结点从下标最大的开始都调用一次MAX-HEAPIFY来建堆。

void buildMaxHeap(int a[],int length) {
    heapSize = length;
    //含有n个结点的堆的下标最大的非叶子结点的标号为(n-2)/2
    for(int i=(length-2)>>1;i>=0;--i)
        maxHeapify(a,i); 
} 

(3)堆排序算法
  调用过程BUILD-MAX-HEAP初始化堆,交换a[0]与堆中最后一个结点,调用MAX-HEAPIFY(a,0),重复这一过程直到堆的大小为1。

void heap_sort(int a[], int length) {
    //初始化堆
    buildMaxHeap(a,length);
    //选择堆的根结点与最后一个结点交换
    for(int i=length-1;i>=1;--i){
        swap(&a[i],&a[0]);
        --heapSize;
        maxHeapify(a,0);
    }
}

3.性能分析
  堆排序的时间效率与带排序数据的顺序无关。

这里写图片描述

4.完整代码

#include<iostream>
using namespace std;

int heapSize = 0;

int  Left(int index) {
    return (index<<1)+1;
}

int Right(int index) {
    return (index<<1)+2;
}

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
//假设以index为结点的左右子树Left(index)和Right(index)都为最大堆
//这时a[index]可能小于其孩子
//maxHeapify通过让a[index]在最大堆中“逐级下降”来维持最大堆的性质 
void maxHeapify(int a[], int index) {
    int l = Left(index);
    int r = Right(index);
    int largest = 0;
    if(l<heapSize && a[l]>a[index])     
        largest = l;
    else largest = index;
    if(r<heapSize && a[r]>a[largest])
        largest = r;
    if(largest != index) {
        swap(&a[largest],&a[index]);
        maxHeapify(a,largest);
    }   
}

void buildMaxHeap(int a[],int length) {
    heapSize = length;
    for(int i=(length-2)>>1;i>=0;--i)
        maxHeapify(a,i); 
} 

void heap_sort(int a[], int length) {
    buildMaxHeap(a,length);
    for(int i=length-1;i>=1;--i){
        swap(&a[i],&a[0]);
        --heapSize;
        maxHeapify(a,0);
    }
}

//输出数组
void print_array(int a[],int n) {
    for(int i=0;i<n;++i){
        cout<<a[i]<<" ";
    }
    cout<<endl;
} 

int main() {
    //直接插入测试数据 
    int a[] = {4,10,16,2,12,9,7};
    int n = 7;
    cout<<"Before sort:";
    print_array(a,n);
    cout<<"After heap-sort:";
    heap_sort(a,n);
    print_array(a,n);
    cout<<endl;

    return 0;   
}

测试结果如下:

这里写图片描述

发布了129 篇原创文章 · 获赞 45 · 访问量 24万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章