二叉堆

二叉堆的基本操作

数据结构表示:

       使用一个一维数组表示,下标从1开始计算,如果是C/C++语言,则忽略下标为0的元素。使用n表示队中元素的个数。

堆的两个基本操作:

      堆关键是理解两个基本操作的实现:

      1、 向堆插入一个结点(上升操作):

             在堆尾(a[n])插入一个元素,然后不断和父节点(a[i/2])比较,如果比父结点大(大根堆)或小(小根堆)就交换,一直到

       堆顶或不再交换就结束。

       C语言代码:

1 void push_heap(int a[],int n){
2     int i = n;
3     int x = a[n];
4     while(i > 1 && a[i/2] < x){
5         a[i] = a[i/2];
6         i /= 2;
7     }
8     a[i] = x;
9 }

(以上代码是大根堆的上升操作,小根堆只需将a[i]>a[j]改为a[i]<a[j]即可)
   具体使用时,先在一维数组后面加入元素,然后调用push_heap函数进行调整。如下面的代码:

1 ++n;
2 a[n]=x;
3 push_heap(a,n);

     2、删除节点:

     删除堆顶节点(下降操作):

     将堆顶节点(堆数组第一个)和堆尾节点(堆数组最后一个)交换,然后删除堆尾节点,将交换后的节点和左右儿子比较大小,交换,

 更换节点编号,如此重复,直到满足堆的性质。

    C语言代码:

    先给一个函数,函数功能是把根为m的非大根堆调整成大根堆,前提条件是这个非大根堆的子堆,也就是根的儿子必须是大根堆。

void heap(int a[],int n,int m){  //n 是数组下标范围,m是需要调整的根的下标
    int t;
    while(m*2 <= n){
        m = m * 2;
        if(m < n && a[m] < a[m+1]){
            m++;
        }
        if(a[m] > a[m/2]){
            t = a[m];
            a[m] = a[m/2];
            a[m/2] = t;
        }
        else
            break;
    }
}

 

   下面的代码是把一个堆的堆顶去掉,并调整堆。

void pop_heap(int a[],int n){
    int x;
    x = a[1];
    a[1] = a[n];
    a[n] = x;
    n--;
    heap(a,n,1);
}

堆排序

  堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

     ①先将初始数组a[1...n]建成一个大根堆,此堆为初始的无序区

     ②再将关键字最大的记录a[1](即堆顶)和无序区的最后一个记录a[n]交换,由此得到新的无序区a[1.n-1]和有序区a[n],且满足a[1..n-1]≤a[n]

     ③由于交换后新的根a[1]可能违反堆性质,故应将当前无序区a[1..n-1]调整为堆。

     然后再将a[1..n-1]中关键字最大的记录a[1]和该区间的最后一个记录a[n-1]交换,由此得到新的无序区a[1..n-2]和有序区a[n-1..n],且满足关系a[1..n-2]≤R[n-1..n],同样要将a[1..n-2]调整为堆。

     重复②③的步骤,直到无序区只有一个元素为止,此时a[1..n]就是一个有序的数组了。

     C语言代码:

//首先建堆,从最底层的元素开始建堆,一直递推到堆顶,即下标为1的数据元素
void make_heap(int a[],int n){
    int i;
    for(i = n/2; i > 0; --i) heap(a,n,i);
}
//堆排序
void heap_sort(int a[],int n){
    int i;
    make_heap(a,n);//先把无序的数据建立成堆
    for(i = n; i > 1; --i){
        int t = a[1];
        a[1] = a[i];
        a[i] = t;
        heap(a,n-i,1);
    }
}

   堆排的时间复杂度约为O(n*logn)

 

posted on 2017-04-02 22:25  smallcowboy  阅读(86)  评论(0)    收藏  举报

导航