zoukankan      html  css  js  c++  java
  • 数据结构--优先列队(堆)的实现与相关操作

        实现优先列队的最普遍的工具是二叉堆,有时也只叫做堆。

        二叉堆有两个性质:结构性和堆序性。

       结构性:堆是一颗被完全填满的二叉树,底层除外,底层元素从左到右依次填入,对于一个完全二叉树,用一个数组来表示一棵树,发现对于数组的任意位置i的元素,他的左儿子在2i处,右儿子在2i+1出,父亲在i/2向下取整处。

       堆序性:如果想要快速找出最小元素,那么任意节点就应该小于它所有的后裔,如果想要快速找到最大的元素,则相反。

       二叉堆在概念上抽象为一颗二叉树,满足上面的两个性质,在程序中则实际上为一个数组,同样满足上面的两个性质。

       下面给出最小堆(即可以以常数时间找出最小元素)的一个代码实现:

       

    #include<iostream>
    
    using namespace std;
    #define MinPQSize 10
    #define MinData -1
    
    struct Heapstruct;
    typedef struct Heapstruct* PriorityQueue;
    
    struct Heapstruct
    {
       int Capacity;
       int Size;
       int *Elements;
    };
    
    
    PriorityQueue Init_priorityqueue(int MaxElements)   //创建并初始化一个优先列队
    {
       PriorityQueue H;
       if(MaxElements < MinPQSize) cout << "Priority queue size is too small" << endl;
    
       H = (PriorityQueue)malloc(sizeof(Heapstruct));
       if(H == NULL) cout << "out of space" << endl;
    
       H->Elements = (int*)malloc(sizeof(int) * MaxElements + 1);
       if(H->Elements == NULL) cout << "out of space" << endl;
    
       H->Capacity = MaxElements;
       H->Size = 0;
       H->Elements[0] = MinData;
    
       for(int i = 1; i <= H->Capacity; ++i)
       {
          H->Elements [i] = 0;  //全部幅值为0
       }
    
       return H;
    }
    
    void Destroy(PriorityQueue H)   //释放一个优先列队
    {
       free(H->Elements);
       free(H);
    }
    
    void MakeEmpty (PriorityQueue H)
    {
       for(int i = 1; i <= H->Capacity; ++i)
       {
          H->Elements[i] = 0;
       }
       H->Size = 0;
    }
    
    bool IsEmpty (PriorityQueue H)
    {
        if(H->Size == 0)
    		return true;
    	else 
    		return false;
    }
    
    bool IsFull (PriorityQueue H)
    {
       if(H->Size == H->Capacity )
           return true;
    	else 
    	   return false;
    }
    
    void Insert(int Key,PriorityQueue H)
    {
    	int i;
    	
    	if(IsFull(H))
    	{
    	   cout << "Priority queue is full" << endl;
    	   return;
    	}
    	//优先列队的队首元素一定为最下元素,插入时先在最后创建一个空穴,在把这个空穴上滤
    	//对于优先列队的任意位置i的元素,他的左儿子在2i处,右儿子在2i+1出,父亲在i/2向下取整处
    	for (i = ++H->Size; H->Elements[i/2] > Key; i /= 2)
    		H->Elements[i] = H->Elements[i/2];
    	H->Elements[i] = Key;
    }
    
    int DeleteMin(PriorityQueue H)
    {
       int i, Child;
       int MinElement, LastElement;
       
       if(IsEmpty(H))
       {
          cout << "Priority queue if Empty" << endl;
    	  return H->Elements[0];
       }
    
       MinElement = H->Elements[1];
       LastElement = H->Elements[H->Size--];
    
       //思想很巧妙,空穴从最低一个位子一直下滤
       for(i = 1; i * 2 <= H->Size; i = Child)
       {
    	   //寻找小的儿子
          Child = i * 2;
    	  if(Child != H->Size && H->Elements[Child + 1] < H->Elements[Child])
    		  Child ++;
    
    	  if(LastElement > H->Elements[Child])
    		  H->Elements[i] = H->Elements[Child];
    	  else
    		  break;
       }
       H->Elements[i] = LastElement;
       return MinElement;
    }
    
    int main ()
    {
    	PriorityQueue H = Init_priorityqueue(11);
    	
    	Insert(16, H);
    	Insert(26, H);
    	Insert(13, H);
    	Insert(14, H);
    	Insert(19, H);
    	Insert(69, H);
    	Insert(32, H);
    	Insert(21, H);
    	Insert(31, H);
    
    	for (int i = 0; i <= 9; ++i)
    	{
    	   cout << DeleteMin(H) << endl;
    	}
       return 0;
    }
    

        因为二叉堆的堆序性,所以可以用来排序,即堆排序,以后会具体论述。

           夜深了,,,

          从未提起,从未忘记。

  • 相关阅读:
    jquery通过live绑定toggle事件
    svn is already locked解决方案
    不安全代码只会在使用 /unsafe 编译的情况下出现
    eclipse 新建 java 文件时自动生成注释
    浅谈权限设计
    ie6/IE8/IE9/谷歌以及火狐等浏览器下li 高度一致解决办法
    PHP+MSSQL TEXT字段被截断的解决方案
    利用CSS让dl dt dd呈现多行多列效果
    CSS实现图片水平垂直居中于DIV
    CSS 关于IE6 margin 为负数 负值的时候 正常显示的方法
  • 原文地址:https://www.cnblogs.com/1242118789lr/p/6817830.html
Copyright © 2011-2022 走看看