数据结构_5

学习过程主要依照中国MOOC课程,感谢MOOC,感谢浙大授课大佬。

堆heap

什么是堆

堆的两个特性:

  • 结构性:用数组表示的完全二叉树
  • 有序性:任一结点的关键字是其子树所有结点的最大值(或最小值)

堆进行的操作

创建、插入、删除、判断是否已满是否为空,返回最大值最小值

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
typedef struct HNode *Heap; /* 堆的类型定义 */
struct HNode {
ElementType *Data; /* 存储元素的数组 */
int Size; /* 堆中当前元素个数 */
int Capacity; /* 堆的最大容量 */
};
typedef Heap MaxHeap; /* 最大堆 */
typedef Heap MinHeap; /* 最小堆 */

#define MAXDATA 1000 /* 该值应根据具体情况定义为大于堆中所有可能元素的值 */

MaxHeap CreateHeap( int MaxSize )
{ /* 创建容量为MaxSize的空的最大堆 */

MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode));
H->Data = (ElementType *)malloc((MaxSize+1)*sizeof(ElementType));
H->Size = 0;
H->Capacity = MaxSize;
H->Data[0] = MAXDATA; /* 定义"哨兵"为大于堆中所有可能元素的值*/

return H;
}

bool IsFull( MaxHeap H )
{
return (H->Size == H->Capacity);
}

bool Insert( MaxHeap H, ElementType X )
{ /* 将元素X插入最大堆H,其中H->Data[0]已经定义为哨兵 */
int i;

if ( IsFull(H) ) {
printf("最大堆已满");
return false;
}
i = ++H->Size; /* i指向插入后堆中的最后一个元素的位置 */
for ( ; H->Data[i/2] < X; i/=2 )
H->Data[i] = H->Data[i/2]; /* 上滤X */
H->Data[i] = X; /* 将X插入 */
return true;
}

#define ERROR -1 /* 错误标识应根据具体情况定义为堆中不可能出现的元素值 */

bool IsEmpty( MaxHeap H )
{
return (H->Size == 0);
}

ElementType DeleteMax( MaxHeap H )
{ /* 从最大堆H中取出键值为最大的元素,并删除一个结点 */
int Parent, Child;
ElementType MaxItem, X;

if ( IsEmpty(H) ) {
printf("最大堆已为空");
return ERROR;
}

MaxItem = H->Data[1]; /* 取出根结点存放的最大值 */
/* 用最大堆中最后一个元素从根结点开始向上过滤下层结点 */
X = H->Data[H->Size--]; /* 注意当前堆的规模要减小 */
for( Parent=1; Parent*2<=H->Size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( X >= H->Data[Child] ) break; /* 找到了合适位置 */
else /* 下滤X */
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;

return MaxItem;
}

/*----------- 建造最大堆 -----------*/
void PercDown( MaxHeap H, int p )
{ /* 下滤:将H中以H->Data[p]为根的子堆调整为最大堆 */
int Parent, Child;
ElementType X;

X = H->Data[p]; /* 取出根结点存放的值 */
for( Parent=p; Parent*2<=H->Size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( X >= H->Data[Child] ) break; /* 找到了合适位置 */
else /* 下滤X */
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
}

void BuildHeap( MaxHeap H )
{ /* 调整H->Data[]中的元素,使满足最大堆的有序性 */
/* 这里假设所有H->Size个元素已经存在H->Data[]中 */

int i;

/* 从最后一个结点的父节点开始,到根结点1 */
for( i = H->Size/2; i>0; i-- )
PercDown( H, i );
}

哈夫曼树与哈夫曼编码

什么是哈夫曼树

根据结点不同的查找频率来构造更有效的搜索树。

带权路径长度(WPL):设二叉树有n个叶子结点,每个叶子结点带有权值wK,从根结点到每个叶子结点的长度为lK,则每个叶子结点的带权路径长度之和就是:WPL= wK*lK从i到k的求和。

哈夫曼树(最优二叉树):WPL最小的二叉树。

哈夫曼树的构造

把权值从小到大进行排序,把权值最小的两个并在一起,形成一棵二叉树,每次把权值最小的两棵二叉树合并。

哈夫曼树的特点

  • 没有度为1的结点;
  • n个叶子结点的哈夫曼树共有2n-1个结点;
  • 哈夫曼树的任意非叶子结点的左右子树交换后仍是哈夫曼树;
  • 对于同一组权值,存在不同构的两棵哈夫曼树;

哈夫曼编码

用二叉树进行编码时如何避免二义性:

  1. 左右分支:0,1
  2. 字符只在叶结点上

利用哈夫曼树进行编码就是哈夫曼编码。

集合及运算

集合运算:交、并、补、差
并查集:集合并、查某元素属于什么集合

集合的表示

可以用树结构表示集合,树的每个结点代表一个集合元素

集合运算

  1. 查找某个元素所在的集合;
  2. 集合的并运算
    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
    #define MAXN 1000                  /* 集合最大元素个数 */
    typedef int ElementType; /* 默认元素可以用非负整数表示 */
    typedef int SetName; /* 默认用根结点的下标作为集合名称 */
    typedef ElementType SetType[MAXN]; /* 假设集合元素下标从0开始 */

    void Union( SetType S, SetName Root1, SetName Root2 )
    { /* 这里默认Root1和Root2是不同集合的根结点 */
    /* 保证小集合并入大集合 */
    if ( S[Root2] < S[Root1] ) { /* 如果集合2比较大 */
    S[Root2] += S[Root1]; /* 集合1并入集合2 */
    S[Root1] = Root2;
    }
    else { /* 如果集合1比较大 */
    S[Root1] += S[Root2]; /* 集合2并入集合1 */
    S[Root2] = Root1;
    }
    }

    SetName Find( SetType S, ElementType X )
    { /* 默认集合元素全部初始化为-1 */
    if ( S[X] < 0 ) /* 找到集合的根 */
    return X;
    else
    return S[X] = Find( S, S[X] ); /* 路径压缩 */
    }

以上。

:转载文章请注明出处,谢谢~