小根堆的增删

来源:互联网 发布:淘宝买万艾可处方单 编辑:程序博客网 时间:2024/06/06 03:03

最小堆,即树根的值是最小的,也是一棵完全二叉树。它以层次结构来区分值的大小。并且最小堆可以帮助我们高效地取出具有最小值。它也是实现优先级队列的高效结构。

using namespace std;    int heap[100];    //下滑操作  void siftDown(int start,int end)  {      //将start号结点向下调整直到end      int i=start,j=2*i;      heap[0]=heap[i]; //用heap[0]来临时保存i结点的值      while(j<=end)      {          //有右孩子并且右孩子比左孩子小时,将j保存右孩子          if(j<end&&heap[j]>heap[j+1]) ++j;          //比j号结点小时,不需调整          if(heap[0]<=heap[j])               break;          else          {              //向下调整              heap[i]=heap[j];              i=j;              j=2*j;          }      }      heap[i]=heap[0];  }    //生成小根堆  void createHeap(int n)  {      memset(heap,0,sizeof(heap)); //初始化heap数组      cout<<"Enter values:"<<endl;      //从下标1开始存      for(int i=1;i<=n;++i)          cin>>heap[i];        int currentPos=n/2; //找到开始调整的位置(即最后一个结点双亲的位置)      while(currentPos>0)      {          siftDown(currentPos,n);          --currentPos;      }  }    //向上调整的函数  //将结点start调整到根结点1为止  void siftUp(int start)  {      int j=start,i=j/2;      heap[0]=heap[j];      while(j>0)      {          if(heap[i]<=heap[0])              break;          else          {              //向上调整工作              heap[j]=heap[i];              j=i;              i=i/2;          }      }      heap[j]=heap[0];  }    //插入操作的实现  bool insert(int x,int& num)  {      ++num;      heap[num]=x;      siftUp(num);            return true;  }    //删除操作  bool removeMin(int& num)  {      heap[1]=heap[num]; //填补树根        --num;      siftDown(1,num); //将根结点下滑到尾部      return true;  }    //前序遍历  void preOrder(int i,int num)  {      if(i<=num)      {          cout<<heap[i]<<" ";            preOrder(2*i,num);          preOrder(2*i+1,num);      }  }    int main()  {      int n=0;      cout<<"Enter the num:";      cin>>n;      createHeap(n);      preOrder(1,n);      cout<<endl;        int val=0;      cout<<"Enter value to insert:";      cin>>val;      insert(val,n);      preOrder(1,n);      cout<<endl;        removeMin(n);      preOrder(1,n);      cout<<endl;  }

最小堆或者最大堆关键的是siftDown和siftUp函数。它们实现了如何将一棵不符合要求的完全二叉树调整为堆。其中值得一提的是,在将结点值往上或往下移动时,我们并不需要马上将元素值交换来反应移动,因为这样有三次赋值操作。我们只需将待调整的结点放在临时空间中,最终找到结点存放的位置时再将其放在合适的位置。


例如:

{      int j=start,i=j/2;      heap[0]=heap[j];      while(j>0)      {          if(heap[i]<=heap[0])              break;          else          {              //向上调整工作              heap[j]=heap[i];              j=i;              i=i/2;          }      }      heap[j]=heap[0];  }


0 0
原创粉丝点击