树——堆的运用

来源:互联网 发布:苹果淘宝app打不开 编辑:程序博客网 时间:2024/05/14 20:32

程序=算法+数据结构。今天所学的是“数据结构”中的“树”。

一、树的定义、特点、一些概念

(1)定义:任意两个节点间有且只有一条路径的无向图。

(2)特点:任意两个节点间有且只有一条路径连接;n个节点有n-1条边;在树中增加一条边会构成回路。

(3)一些概念:根(没有父节点的节点)、父节点、子节点、叶节点(没有子节点的节点)、内部节点、深度(从根到节点的层数)。

二、二叉树

(1)定义:每个节点最多有两个子节点的树。

(2)特殊二叉树:满二叉树(每个内部节点都有两个子节点,即有2^h-1个节点,h为深度);完全二叉树(即最后一层从右向左连续缺少若干个节点,其余各层都是满的)。

(3)应用:堆\并查集。

(4)Tip:可以只用一维数组存储完全二叉树(此时S型穿插,记图)。

三、

堆是一种特殊的完全二叉树,分为最小堆和最大堆。最小堆是所有父节点都比子节点要小的完全二叉树,最大堆是所有父节点都比子节点要大的完全二叉树。

1、建立堆

(1)建立最小堆

首先,创建用来存放堆的数组,假如为h[101],堆的大小为n;

接着,读入n个数据到数组h[ ]中;

最后,对这n个数据进行建堆;

代码如下:

#include

int h[101];

int n;

void swap(int x,int y)

{

     int t;

      t=h[x];

     h[x]=h[y];

     h[y]=t;

     return;

}

void siftdown(int i)

{

     int t,flag=0;

    while(i*2<=n&&flag==0)

    {

            if (h[i]>h[i*2])

                  t=i*2;

            else

                  t=i;//已经用t作为标记,因而t=i或者t=i*2,也就是t编号可能为父节点编号,又可能为左儿子编号

             

            if (i*2+1<=n)

               if(h[t]>=h[i*2+1])//此时可能是父节点编号和右儿子比,也可能是左节点和右节点对比

                      t=i*2+1;

 

             if(t!=i)//因为t表示的是三者(两者)中最小的编号,而i表示的肯定是父节点的编号,

                    //因此如果两者不相等,说明有比它更小的

           {

                 swap(t,i);

                 i=t;//把最小的和它交换

            }

           else

                  flag=1;      

     }

     return;

}

 

void creat()

{

     int i;

     for(i=n/2;i>=1;i--)

          siftdown(i);

      return;

}

 

int main()

{

    int i,num;

    scanf("%d",&num);

    for(i=1;i<=num;i++)

         scanf("%d",&h[i]);

     n=num;

   creat();

    ……

}

 

(2)建立最大堆

     最大堆的建立和最小堆的建立一样,只是将siftdown( )函数相应的修改,即用t记录值较大的节点编号。

       

2、堆的运用——堆排序

(1)利用最大堆排序

     void heapsort()
     {
          while(n>1)
         {
              swap(1,n);
              n--;
              siftdown(1);
           }
          return;
      }

      其中,siftdown()函数是建立最大堆的函数。经heapsort()函数后,数组h[n]已经从小到大排好顺序。

 

(2)利用最小堆排序

       int deletemax()
       {
             int t;
             t=h[1];
             h[1]=h[n];
             n--;
             siftdown(1);
              returnt;
         }

         此时的siftdown()函数是建立最小堆的函数,保证了t值肯定是最小堆的堆顶,也就是数组的最小值。

 

0 0
原创粉丝点击