一、树
1.1 树的基本概念
Name | Description |
---|
结点的度 | 该结点子结点个数 |
度为2的树 | 至少有三个结点 |
二叉树 | 可为空 |
1.2 树的性质
- 结点数=所有结点的度数+1
- 度为 m 的树,第i层至多有 mi-1 个结点
- 高为 h 的 m 叉树,至多有 (mh-1)/(m-1) 个结点
- n 个结点的 m 叉树,最小高度 ⌈logm(n(m-1)+1)⌉
- n 个结点的树有 n-1 条边,N1+2N2+3N3+…+mNm=N0+N1+N2+…+Nm
1.3 树的存储结构
1.3.1 双亲表示法
#define MAX_TREE_SIZE 100
typedef int TElemType;
typedef struct PTNode
{
TElemType data;
int parent;
}PTNode;
typedef struct
{
PTNode nodes[MAX_TREE_SIZE];
int r;
int n;
}PTree;
1.3.2 孩子表示法
#define MAX_TREE_SIZE 100
typedef char TElemType;
typedef struct CTNode
{
int child;
struct CTNode *next;
} *ChildPtr;
typedef struct
{
TElemType data;
int parent;
ChildPtr firstchild;
} CTBox;
typedef struct
{
CTBox nodes[MAX_TREE_SIZE];
int r, n;
}
1.3.3 孩子兄弟表示法
typedef struct CSNode{
TElemType data;
struct CSNode *firstchild, *rightsib;
}CSNode,*CSTree;
1.4 树、森林与二叉树之间的转换
1.5 树、森林与二叉树的遍历的对应关系
树 | 森林 | 二叉树 |
---|
先根遍历 | 先序遍历 | 先序遍历 |
后根遍历 | 中序遍历 | 中序遍历 |
二、二叉树
2.1 二叉树的性质
- 是有向树
- 一般二叉树性质:
- N0+N1+N2=N1+2N2+1故 N0=N2+1
- 第 i 层,至多有 2i-1 个结点
- 高为 h,至多有 2h-1 个结点
- 完全二叉树性质:
- i 的双亲结点i/2
- i 的左孩子2i,右孩子2i+1
- i 所在层次 ⌈log2(i+1)⌉
- n 个结点完全二叉树高 ⌈log2(n+1)⌉
2.2 二叉树的存储结构
2.2.1 顺序存储
2.2.2 链式存储
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode {
ElementType Data;
BinTree Left;
BinTree Right;
};
三、二叉树的遍历
3.1 递归(先、中、后)
void PreorderTraversal( BinTree BT ) {
if( BT ) {
printf("%d ", BT->Data );
PreorderTraversal( BT->Left );
PreorderTraversal( BT->Right );
}
}
void InorderTraversal( BinTree BT ) {
if( BT ) {
InorderTraversal( BT->Left );
printf("%d ", BT->Data);
InorderTraversal( BT->Right );
}
}
void PostorderTraversal( BinTree BT ) {
if( BT ) {
PostorderTraversal( BT->Left );
PostorderTraversal( BT->Right );
printf("%d ", BT->Data);
}
}
3.2 非递归(先、中、后)(堆栈)
void InOrderTraversal(BinTree BT) {
BinTree T=BT;
Stack S=CreatStack(MaxSize);
while(T||!IsEmpty(S)) {
while(T) {
Push(S,T);
T=T->Left;
}
if(!IsEmpty(S)) {
T=Pop(S);
printf("%5d",T->Data);
T=T->Right;
}
}
}
void PreOrderTraversal(BinTree BT) {
BinTree T=BT;
Stack S=CreatStack(MaxSize);
while(T||!IsEmpty(S)) {
while(T) {
printf("%5d",T->Data);
Push(S,T);
T=T->Left;
}
if(!IsEmpty(S)) {
T=Pop(S);
T=T->Right;
}
}
}
void PostOrderTraversal(BinTree BT) {
BinTree T=BT;
BinTree Exist=NULL;
Stack S=CreatStack(MaxSize);
while(T||!IsEmpty(S)) {
while(T && T->Left!=Exist && T->Right!=Exist) {
Push(S,T);
T=T->Left;
}
if(!IsEmpty(S)) {
T=GetTop(S);
if(T->Right && T->Right!=Exist) {
T=T->Right;
} else {
T=Pop(S);
printf("%5d",T->Data);
Exist=T;
T=GetTop(S);
}
}
}
}
3.3 层序遍历(队列)
void LevelorderTraversal ( BinTree BT ) {
Queue Q;
BinTree T;
if ( !BT )
return;
Q = CreatQueue();
AddQ( Q, BT );
while ( !IsEmpty(Q) ) {
T = DeleteQ( Q );
printf("%d ", T->Data);
if ( T->Left )
AddQ( Q, T->Left );
if ( T->Right )
AddQ( Q, T->Right );
}
}
3.4 二叉树遍历的应用
void PreorderTraversal( BinTree BT ) {
if( BT ) {
if(!BT->Left&&!BT->Right)
printf("%d ", BT->Data );
PreorderTraversal( BT->Left );
PreorderTraversal( BT->Right );
}
}
int PostOrderGetHeight(BinTree BT){
int HL, HR, MaxH;
if(BT){
HL=PostOrderGetHeight(BT->Left);
HR=PostOrderGetHeight(BT->Right);
MaxH=(HL>HR)?HL:HR;
return(MaxH+1;)
}else{
return 0;
}
}
四、二叉搜索树
Position Find(ElementType X, BinTree BST) {
if(!BST)
return NULL;
if(X > BST->Data)
return Find(X, BST->Right);
else if(X < BST->Data)
return Find(X, BST->Left);
else
return BST;
}
Position IterFind (ElementType X, BinTree BST) {
while(BST) {
if(X > BST->Data)
BST = BST->Right;
else if(X < BST->Data)
BST = BST->Left;
else
return BST;
}
return NULL;
}
Position FindMin(BinTree BST) {
if(!BST)
return NULL;
else if(!BST->Left)
return BST;
else
return FindMin(BST->Left);
}
Position FindMax(BinTree BST) {
if(BST)
while(BST0->Right)
BST=BST->Right;
return BST;
}
BinTree Insert( BinTree BST, ElementType X ) {
if( !BST ) {
BST = (BinTree)malloc(sizeof(struct TNode));
BST->Data = X;
BST->Left = BST->Right = NULL;
} else {
if( X < BST->Data )
BST->Left = Insert( BST->Left, X );
else if( X > BST->Data )
BST->Right = Insert( BST->Right, X );
}
return BST;
}
BinTree Delete( BinTree BST, ElementType X ) {
Position Tmp;
if( !BST )
printf("要删除的元素未找到");
else {
if( X < BST->Data )
BST->Left = Delete( BST->Left, X );
else if( X > BST->Data )
BST->Right = Delete( BST->Right, X );
else {
if( BST->Left && BST->Right ) {
Tmp = FindMin( BST->Right );
BST->Data = Tmp->Data;
BST->Right = Delete( BST->Right, BST->Data );
} else {
Tmp = BST;
if( !BST->Left )
BST = BST->Right;
else
BST = BST->Left;
free( Tmp );
}
}
}
return BST;
}
五、平衡二叉树
- h 层AVL树的最少结点数:
- N1 = 1、 N2 = 2
- Nh = N(h-1) + N(h-2) + 1
typedef struct AVLNode *Position;
typedef Position AVLTree;
struct AVLNode {
ElementType Data;
AVLTree Left;
AVLTree Right;
int Height;
};
int Max ( int a, int b ) {
return a > b ? a : b;
}
AVLTree SingleLeftRotation ( AVLTree A ) {
AVLTree B = A->Left;
A->Left = B->Right;
B->Right = A;
A->Height = Max( GetHeight(A->Left), GetHeight(A->Right) ) + 1;
B->Height = Max( GetHeight(B->Left), A->Height ) + 1;
return B;
}
AVLTree DoubleLeftRightRotation ( AVLTree A ) {
A->Left = SingleRightRotation(A->Left);
return SingleLeftRotation(A);
}
AVLTree Insert( AVLTree T, ElementType X ) {
if ( !T ) {
T = (AVLTree)malloc(sizeof(struct AVLNode));
T->Data = X;
T->Height = 0;
T->Left = T->Right = NULL;
}
else if ( X < T->Data ) {
T->Left = Insert( T->Left, X);
if ( GetHeight(T->Left)-GetHeight(T->Right) == 2 )
if ( X < T->Left->Data )
T = SingleLeftRotation(T);
else
T = DoubleLeftRightRotation(T);
}
else if ( X > T->Data ) {
T->Right = Insert( T->Right, X );
if ( GetHeight(T->Left)-GetHeight(T->Right) == -2 )
if ( X > T->Right->Data )
T = SingleRightRotation(T);
else
T = DoubleRightLeftRotation(T);
}
T->Height = Max( GetHeight(T->Left), GetHeight(T->Right) ) + 1;
return T;
}
六、堆
- 结构性:用数组表示的完全二叉树
- 有序性:任一结点的KEY是其子树所有结点的最大值(最小值)
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 ) {
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 ) {
int i;
if ( IsFull(H) ) {
printf("最大堆已满");
return false;
}
i = ++H->Size;
for ( ; H->Data[i/2] < X; i/=2 )
H->Data[i] = H->Data[i/2];
H->Data[i] = X;
return true;
}
#define ERROR -1
bool IsEmpty( MaxHeap H ) {
return (H->Size == 0);
}
ElementType DeleteMax( MaxHeap 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++;
if( X >= H->Data[Child] )
break;
else
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
return MaxItem;
}
void PercDown( MaxHeap H, int 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++;
if( X >= H->Data[Child] )
break;
else
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
}
void BuildHeap( MaxHeap H ) {
int i;
for( i = H->Size/2; i>0; i-- )
PercDown( H, i );
}
七、哈夫曼树与哈夫曼编码
- 带权路径长度WPL
- 哈夫曼树(最优二叉树):WPL最小的树
- 哈夫曼树特点:
- 没有度为1的结点
- n个叶子结点的哈夫曼树共有2n-1个结点(n2=n0-1)
- 任意非叶结点的左右子树交换后仍是哈夫曼树
- 对同一组权值,可能存在不同构的几个哈夫曼树,但是WPL是一样的
- 哈夫曼编码:
- 不等长编码
- 前缀码:避免二义性,任何字符的编码不是另一个字符编码的前缀
- 用二叉树进行编码:
- 可左右分支 0、1
- 字符只在叶结点上(如果有字符在非叶结点上,则其子树上的叶结点编码不是前缀码)
- 利用哈夫曼树构造前缀码代价最小
typedef struct TreeNode *HuffmanTree;
struct TreeNode {
int Weight;
HuffmanTree Left, Right;
};
HuffmanTree Huffman(MinHeap H) {
int i;
HuffmanTree T;
BuildMinHeap(H);
for(int i=1; i<H->Size; i++) {
T=(HuffmanTree)malloc(sizeof(struct TreeNode));
T->Left=DeleteMin(H);
T->Right=DeleteMin(H);
T->Weight=T->Left+T->Right->Weight;
Insert(H,T);
}
T=DeleteMin(H);
return T;
}
八、集合及运算(并查集)
- 集合运算:交、并、补、差、判断是否属于某一集合
- 并查集:集合并、查某元素属于什么集合
- 并查集问题中集合的存储:
- 1.树表示,每个结点代表一个集合元素
双亲表示法,孩子指向双亲 - 2.数组表示,data + parent (根的parent为 -1,或 -集合中元素个数)
typedef struct {
ElementType Data;
int Parent;
} SetType;
int Find(SetType S[], ElementType X) {
int i;
for(i=0; i<MaxSize&&S[i].Data!=X; i++);
if(i>=MaxSize)
return -1;
for(; S[i].Parent>=0; i=S[i].Parent);
return i;
}
void Union(SetType S[], ElementType X1, ElementType X2) {
int Root1, Root2;
Root1=Find(S,X1);
Root2=Find(S,X2);
if ( S[Root2] < S[Root1] ) {
S[Root2] += S[Root1];
S[Root1] = Root2;
} else {
S[Root1] += S[Root2];
S[Root2] = Root1;
}
}
九、Practice
03-树1 树的同构
03-树2 List Leaves
03-树3 Tree Traversals Again
04-树4 是否同一棵二叉搜索树
04-树5 Root of AVL Tree
04-树7 二叉搜索树的操作集
05-树7 堆中的路径
05-树8 File Transfer