算法导论第六章思考题6-2: 对d堆的分析

/****************************************************************************************

 * (1) 显然索引为i的节点的子节点为区间 [ d*(i-1)+2,d*(i-1)+d+1 ];

 * (2) logdN;

 * (3) 见下面_adjust()函数,运行时间为:Θ(d*logdN)

 * (4) 见下面_insert()函数,插入单个元素运行时间为:Ο(logdN)最坏情形也就这样了;

 * (5) 该问要求实现最大优先队列中的一个以d堆为基的函数:将元素x的关键字的值增加到k,同时保持最大(小)堆性质。很简单,直接更新x键值,再执_adjust()即可。

****************************************************************************************/

   

 

1

 2

 3

 4

 5

 6

 7

 8

 9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

#include<iostream>

using namespace std;

 

const int d=3;

 

//调整法建堆实际上是自顶而下的,后面的插入法则是自下而上

void _adjust(int a[],int holeIndex ,int n)

{

  int j=d*( holeIndex -1)+2;

  int item=a[holeIndex];

  while(j<=n)

  {

    int sub_max=a[j],pos=j;

    for(int k=1;k<d;k++){ //d个子节点中寻找最大子节点

        if((j+k<=n)&&(sub_max<a[j+k])){

            sub_max=a[j+k];

            pos=j+k; //存储最大子节点的下标

            }

     }

     if(item<sub_max) a[holeIndex]=sub_max;

     holeIndex=pos;

     j= d*( holeIndex -1)+2;

    }

    a[holeIndex]=item;

}

 

//以下为测试程序

int main()

{

    int a[13]={0,4,1,3,2,16,7,9,10,14,8,23,5};

    for(int i=12/d;i>0;i--){

    _adjust(a,i,12);

    }

    for(int i=1;i<=12;i++) cout<<a[i]<<" ";

    cin.get();

    return 0;

}

 

 

//_insert()函数

 

#include<iostream>

using namespace std;

 

const int d=3;

int a[13]={0,4,1,3,2,16,7,9,10,14,8,23,5};

int b[13]={0};

 

void _insert(int b[],int value,int n)

{

    int i=n;

    while((i>1)&&(b[(i-2)/d+1]<value)){

        b[i]=b[(i-2)/d+1];

        i=(i-2)/d+1;

    }

    b[i]=value;

}

 

int main()

{

    for(int i=1;i<=12;i++){

    _insert(b,a[i],i);

    }

    for(int i=1;i<=12;i++)   cout<<b[i]<<" ";

    cin.get();

    return 0;

}

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值