堆的基本操作——基于数组实现

SiftUp

void siftUp(int i)
{
  bool done = false;
  if(i==1) return;//根节点,无法上移
  while(true)
  {
    if(h[i]>h[i/2]) 
    {
      int temp = h[i];
      h[i] = h[i/2];
      h[i/2] = temp;
     }
     else 
       done = true;
      i/=2;
      if(done || i==1 || i==0) break;//忽略i==0
    }
  }

siftDown

void siftDown(int i)//i为索引,n为数组元素个数
{
  bool done = false;
  if(2*i>n) return;
  while(true)
  {
    i*=2;
    if(i+1<=n&&h[i+1]>h[i]) i+=1;//取左右孩子中最大的那一个
    if(h[i/2]<h[i]) 
    {
      int temp = h[i];
      h[i] = h[i/2];
      h[i/2] = temp;
    }
    else done = true;
    if(done || 2*i>n) break;
  }
}

insert

void insert(int x)
{
  n = n+1;
  h[n] = x;
  siftUp(n);
}

delete

void del(int i)
{
  int x = h[i];
  int y = h[n];
  n = n-1;
  if(i=n+1) return;
  h[i] = y;
  if(y>x) siftUp(i);
  else siftDown(i);
}

makeHeap

void makeHeap()
{
  for(int i=n/2;i>=1;i++)
    siftDown(i);
 }

全部代码

#include<iostream>
using namespace std;
int h[1005];//数组 
int n;//元素个数
void siftUp(int i)
{ 
  bool done = false;
  if(i==1) return;//根节点,无法上移
  while(true)
  { 
    if(h[i]>h[i/2]) 
    {
      int temp = h[i];
      h[i] = h[i/2];
      h[i/2] = temp;
    }
     else 
       done = true;
    i = i/2;
    if(i==1 ||i==0 || done) break;
  }
}

void siftDown(int i)//i为索引
{
  bool done = false;
  if(2*i>n) return;
  while(true)
  { 
    i = 2*i;
    if(i+1<=n&&h[i+1]>h[i]) i+=1;//取左右孩子中最大的那一个
    if(h[i/2]<h[i]) 
    {
      int temp = h[i];
      h[i] = h[i/2];
      h[i/2] = temp;
    }
    else done = true;
    if(done ||2*i>n) break;
  }
}

void insert(int x)
{
  n = n+1;
  h[n] = x;
  siftUp(n);
}

void del(int i)
{
  int x = h[i];
  int y = h[n];
  n = n-1;
  if(i=n+1) return;
  h[i] = y;
  if(y>x) siftUp(i);
  else siftDown(i);
}

void makeHeap()
{
  for(int i = n/2;i>=1;i--)
    siftDown(i);
 }
 
void print()
{
	for(int i=1;i<=n;i++)
	  cout<<h[i]<<" ";
}

int main()
{
	cout<<"请输入元素个数:"<<endl;
	cin>>n;
	for(int i=1;i<=n;i++)
	  cin>>h[i];
	makeHeap();
	print();
	cout<<endl;
	insert(4);
	print();
	cout<<endl;
	del(2);
	print();
	cout<<endl;
	return 0;
}
 

时间复杂度

所有操作的时间复杂度为O(logn),创建堆的时间复杂度为O(n)

着重分析创建堆

南京理工大学PPT

总结

容易在循环判断的地方出错,开始是直接在while(done || 2*i>n)导致没有进入循环,后来是循环条件出错,导致死循环。以后要注意循环!!!

posted @ 2020-04-08 22:06  南理工学渣  阅读(41)  评论(0)    收藏  举报