Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1062127
  • 博文数量: 77
  • 博客积分: 821
  • 博客等级: 军士长
  • 技术积分: 1905
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-23 16:17
个人简介

学校:上海交通大学软件工程 学历:硕士 行业:从事流媒体移动开发 QQ: 412595942 邮箱:yiikai1987910@gmail.com

文章分类

全部博文(77)

文章存档

2016年(4)

2015年(15)

2014年(16)

2013年(12)

2012年(21)

2011年(9)

分类: C/C++

2012-11-23 10:34:12

    今天的主角-----堆
    很多情况下,大家可能会有这么一个想法,给我一串数据,但是,我只focus当前这串数据的最大值或最小值,也就是说,我只想取出这串数据的最大值或最小值,而后续的数我并不关心。而在取出一个数之后,我对这串剩下的数据在进行取数操作,也是只关心当前数据中的最大或最小值,后续的数据如何排列也漠不关心。对于这类问题,堆就提供了一个良好的解决方案。  这时候如果你稍微动动脑子,也就能明白什么是推排序了吧   没错! 每次从这串数据中拿出的都是当前最大的数,自然当你全都拿出来后,数据也自然排列好了!  真实个不错的算法,那我们就先来看看堆的概念吧!
    
   堆其实是一颗2叉树,注意,它仅仅是棵二叉树,并没有一定的顺序排列,化而言之,其实你就直接可以把一个数组按照树的逐层遍历来构造这么一颗2叉树(什么叫逐层呢? 其实就是将一个二叉树从上往下,从左往右依次铺开 如下图)
  
这种逐层安排出来的二叉树有什么特点呢? 仔细看就能发现,一个数组有6个元素,6/2=3,看下,是不是只有0,1,2这三个元素在这颗树上才有子节点呢?没错吧,这样对于我们后续的排序大小堆是很有帮助的!
接着看,还有一个很重要的性质就是,假设每个父节点在数组中的位置是i,每个父节点的子节点必定是i*2+1(左节点),i*2+2(右节点),这真是很有用的性质,方便了我们排序大小堆。
   好了有了这两个性质,我们来看下怎么来进行大堆排序吧(小堆的做法相仿)
   大堆的排序是部分排序,即只要关注每个子节点和父节点直接的大小关系就可以了(见下图)
   
从上图可以看出,其实就是从父子节点中找出最大的那个数然后放在父节点的位置,这样几次过后,堆顶一定是存放最大的数。这样一来大堆就实现了!很简单吧!

  那堆排序又是如何进行的呢?其实跟简单,就是讲堆顶元素取走,然后用堆尾元素将其替换(堆尾元素其实就是堆的右下方的元素),之后再对该堆进行大堆规范的排列调整 (见下图)

  
这样重复取出,最终自然就能得到一个从大到小的排序序列了

   好了概念讲完了,最后还是上实现代码,什么都不如代码来的方便,一目了然!!!!!
    

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <iostream>
  4. #include <vector>
  5. using namespace std;
  6. int data[13]={13,7,2,9,6,4,15,17,18,45,1,10,16};

  7. struct node{
  8.     int num;
  9.     struct node *left;
  10.     struct node *right;
  11. };
  12. typedef struct node node_t;

  13. node_t *topHeap = NULL;

  14. void createBigHeap(int num)
  15. {
  16.     int size = num;
  17.     int i = size / 2; //为什么要把数组的总数除以2呢? 你会发现,其实只有这些数才会有子节点
  18.     int j = i - 1;
  19.     //下这个for循环主要就是进行大堆的排序
  20.     for(;j >= 0;j--)
  21.     {
  22.         if((j*2+1)<size && data[j]<data[j*2+1])
  23.         {
  24.             if((j*2+2)<size && data[(j*2+1)] < data[(j*2+2)])
  25.             {
  26.                 int tmp = data[j*2+2];
  27.                 data[j*2+2] = data[j];
  28.                 data[j] = tmp;
  29.             }
  30.             else{
  31.                 int tmp = data[j*2+1];
  32.                 data[j*2+1] = data[j];
  33.                 data[j] = tmp;
  34.             }
  35.         }
  36.         else if((j*2+1)<size && data[j]>data[j*2+1])
  37.         {
  38.             if((j*2+2)<size && data[j] < data[(j*2+2)])
  39.             {
  40.                 int tmp = data[j*2+2];
  41.                 data[j*2+2] = data[j];
  42.                 data[j] = tmp;
  43.             }
  44.         }
  45.     }
  46. }

  47. void sortHeap(int num)
  48. {
  49.     vector<int> sortdata;
  50.     int i = num - 1;
  51.     int j = 0;
  52.     //以下这个for循环就是将堆内最后的元素和堆顶元素进行互换,并且移除堆顶元素
  53.     for(;i>0;i--)
  54.     {
  55.         sortdata.push_back(data[j]);
  56.         data[j] = data[i];
  57.         num--;
  58.         createBigHeap(num);
  59.     }
  60.     sortdata.push_back(data[j]);
  61.     vector<int>::iterator itr;
  62.     for(itr = sortdata.begin();itr != sortdata.end();itr++)
  63.     {
  64.         cout<<*itr<<endl;
  65.     }
  66. }

  67. int main()
  68. {
  69.     int num = sizeof(data) / 4;
  70.     createBigHeap(num);
  71.     sortHeap(num);
  72. }
好了 今天就讲到这了

阅读(6766) | 评论(2) | 转发(1) |
给主人留下些什么吧!~~

DBOYaoao2012-11-29 16:38:25

擦  被你js会的杠杠的

terrylu872012-11-28 16:32:38

你这边没有想象的火啊。
我用js随便写了一个 heap_sort

function run_heap_test()
{
  // var test_val = [4,3,7,43,51,97,23];
  var test_val = [5,45,38,21,17,13,7];
  print_array(test_val);
  heap_sort(test_val);
  print_array(test_val);
}

function heap_adjust(data,begin,end)
{
  var i=begin;
  while(i<(end/2)){
    if((2*i+2)