*个人学习笔记*
树与二叉树
1. 二叉树的性质
性质1:在二叉树的第i层上至多有2^(i-1)个结点(i>=1)。
性质2:深度为k的二叉树上至多含2^k-1个结点(k>=1)。
性质3:对任何一棵二叉树T,设叶子结点数为n0,度为2的结点数为n2,那么,n0=n2+1。
性质4:具有n个结点的完全二叉树的深度为log2n+1。
性质5:对有n个结点的完全二叉树的结点按层序编号,则对任一结点i(1<=i<=1),有:
- 如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是i/2;
- 如果2i>n,则结点i无左孩子;如果2i<=n,则其左孩子是2i;
- 如果2i+1>n,则结点i无右孩子;如果2i+1<=n,则其右孩 子是2i+1。
2. 二叉树的存储
//链式存储
/*二叉链表*/
typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild;
}BiTreeNode, *BiTree;
/*三叉链表*/
typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;
2. 二叉树的遍历
//先序遍历
void PreOrder(BiTree bt)
{
if(bt != NULL)
{
visit(bt->data);
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
}
//中序遍历
void PreOrder(BiTree bt)
{
if(bt != NULL)
{
PreOrder(bt->lchild);
visit(bt->data);
PreOrder(bt->rchild);
}
}
//后序遍历
void PreOrder(BiTree bt)
{
if(bt != NULL)
{
PreOrder(bt->lchild);
PreOrder(bt->rchild);
visit(bt->data);
}
}
//层次遍历算法
void LevelOrder(BiTree bt)
{
BiTreeNode Queue[MAXNODE];
int front,rear;
if(bt == NULL) return;
front = -1; rear = 0;
Queue[rear] = bt;
while (rear != front)
{
front++;
visit(Queue[front]->data);
if (queue[front]->lchild != NULL)
{
rear++;
Queue[rear] = Queue[front]->lchild;
}
if (queue[->rchild != NULL])
{
rear++;
Queue[rear] = Queue[front]->rchild;
}
}
}
3. 二叉树的构建
void CreatBiTree(char preord[], char inord[], int n, BiTree root)
{ //n为二叉树结点的个数,建立的二叉树放在root中
if (n <= 0) root = NULL;
else PreInOrd(preord, inord, 1, n, 1, n, &root);
}
void PreInOrd(char preord[], char inord[], int i, int j, int k, int h, BiTree *t)
{ //先序序列中从i到j,中序序列从k到h,建立一棵二叉树放在t中
int m;
*t = new BiNode;
(*t)->data = preord[i];
m = k;
while (inord[m] != preord[i]) m++;
if (m == k) (*t)->lchild = NULL; //左子树空
else PreInOrd(preord, inord, i+1, i+m-k, k, m-1, &(*t)->lchild);
if (m == h) (*t)->rchild = NULL; //右子树空
else PreInOrd(preord, inord, i+m-k+1, j, m+1, h, &(*t)->lchild);
}
//统计叶子结点个数
int CountLeaf(BiTree T)
{
if (T == NULL) return 0;
if (T->lchild == NULL && T->rchild == NULL) return 1;
return CountLeaf(T->lchild) + CountLeaf(T->rchild);
}
//计算二叉树深度算法
int BitreeDepth (BiTree bt)
{
if (bt == NULL) return 0;
if (bt->lchild == NULL && bt->rchild == NULL) return 1;
depthL = BitreeDepth(bt->lchild);
depthR = BitreeDepth(bt->rchild);
return 1+max(depdthL, depthR);
}
4. 二叉排序树(BST)的删除
Status DeleteBST(BiTree &T, KeyType key)
{
if (!T) return FALSE;
else
{
if (key == T->data.key)
{ //找到关键字等于key的数据元素
Delete(T);
return TRUE;
}
else if (key < T->data.key)
DeleteBST(T->lchild, key);
else
DeleteBST(T->rchild, key);
}
}
void Delete(BiTree &p)
{ //从二叉排序树中删除结点p,并重接它的左子树或右子树
if (!p->lchild && !p->rchild) free(&p);
if (!p->rchild) //只有左子树
{
q = p;
p = p->lchild;
f->lchild = p; //两种情况,或者:f->rchild = p;
free(q);
}
else if (!p->lchild) //只有右子树
{
q = p;
p = p->rchild;
f->lchild = p; //两种情况,或者:f->rchild = p;
free(q);
}
else //左右子树均有
{
q = p;
s = p->lchild;
while (s->rchild)
{
q = s;
s = s->rchild;
} //s指向被删结点p的前驱,q与s同步
p->data = s->data;
if (q != p) q->rchild = s->lchild;
else q->lchild = s->lchild; //重接q的左子树
free(s);
}
}
5. 平衡二叉树(AVL)的插入
AvlTree Insert(ElementType X, AvlTree T)
{
if (T == NULL)
{ //Create and return a one node tree
T = malloc(sizeof(struct AvlNode));
if (T == NULL) FatalError("Out of space!!!");
else
{
T->Element = X;
T->Height = 0;
T->Left = T->Right = NULL;
}
}
else if (X < T->Element)
{ //Handle left insertion
T->Left = Insert(X, T->Left);
if (Height(T->Left) - Height(T->Right) == 2) //not balanced
if (X < T->Left->Element) //LL Rotation
T = SingleRotateWithLeft(T);
else //LR Rotation
T = DoubleRotateWithLeft(T);
}
else if (X > T->Element)
{ //Handle right insertion
T->Right = Insert(X, T->Right);
if (Height(T->Right) - Height(T->Left) == 2)
if (X > T->Right->Element)
T = SingleRotateWithRight(T);
else
T = DoubleRotationWithRifht(T);
}
//Else X is in the tree already;we'll do nothing
T->Height = Max(Height(T->Left), Height(T->Right)) + 1;
return T;
}
AvlTree SingleRotateWithLeft(AvlTree T) //LL Rotation
{
AvlTree pT = T, pT2 = T->Left->Right;
T = T->Left;
T->Right = pT;
pT->Left = pT2;
return T;
}
6. 最优树-哈夫曼树
//哈夫曼编码的算法实现
#define MAXBIT 10
#define MAXVALUE 1000
typedef struct HNode //结点
{
int weight;
int parent, lchild, rchild;
}HNode;
typedef struct HCode //哈夫曼编码结构
{
int bit[MAXBIT];
int start;
}HCode;
void HuffmanCoding(HNode *HT, HCode *HC, int *w, int n)
{ //w存放n个字符的权值,构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC。
if (n <= 1) return;
m = 2*n-1;
HT = (HNode *)malloc(m*sizeof(HNode)); //哈夫曼树的构造
for (p = HT, i = 1; i < n; ++i, ++p, ++w)
{ //初始化叶子结点信息
(*p)->weight = *w;
(*p)->lchild = -1;
(*p)->rchild = -1;
(*p)->parent = -1;
}
for (; i < m; ++i, ++p)
{ //初始化分支结点信息,非叶子节点
(*p)->weight = 0;
(*p)->lchild = -1;
(*p)->rchild = -1;
(*p)->parent = -1;
}
for (i = n; i < m; ++i)
{ //寻找根节点权值最小和次最小的两棵子树
m1 = m2 = MAXVALUE;
x1 = x2 = 0;
for (j = 0; j < i; ++j)
{
if (HT[j].parent == -1 && HT[j].weight < m1)
{
m2 = m1;
x2 = x1;
m1 = HT[j].weight;
x1 = j;
}
else if (HT[j].parent == -1 && HT[j].weight < m2)
{
m2 = HT[j].weight;
x2 = j;
}
}
//合并成一棵新的子树
HT[x1].parent = i;
HT[x2].parent = i;
HT[i].lchild = x1;
HT[i].rchild = x2;
HT[i].weight = m1 + m2;
}
//字符编码
HC = (HCode *)malloc(n)*sizeof(HCNode);
for (i = 0; i < n; ++i)
{
start = n - 1; //最后一个非叶子结点的位置
for (c = i, f = HT[i].parent; f != 1; c = f, f = HT[f].parent)
if (HT[f].lchild = c) HC[i].bit[start--] = 0;
else HC[i].bit[start--] = 1;
HC[i].start = start + 1; //记录编码的起始位置
}
}
7. 树和森林
//树的双亲表示法
#define MAX_TREE_SIZE 100
typedef struct PTNode
{
DataType data;
int parent;
}PTNode;
typedef struct PTree
{
PTNode nodes[MAX_TREE_SIZE];
int r, n;
}PTree;
//树的孩子表示法
typedef struct CTNode
{
int child;
struct CTNode *next;
}CTNode;
typedef struct CTBox
{
DataType data;
CTNOde *firstchild;
}CTBox;
typedef struct CTree
{
CTBox nodes[MAX_TREE_SIZE];
int n, r;
}CTree;
//树的孩子兄弟表示法
typedef struct CSNode
{
DataType data;
struct CSNode *firstchild, *nextsibling;
}CSNode;