关于树及其操作

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#define ElemType int
#define MaxSize 100
using namespace std;
/*树的基本概念
空树-结点数为0的树(森林也有空森林)
非空树:
	1.有且仅有一个根结点;
	2.没有后继的结点称为“叶子结点(终端结点)”;
	3.有后继的结点称为“分支结点(非终端结点)”;
	4.除了根结点,每个结点都有且仅有一个前驱,可以有0个或多个后继。
!树是一种递归定义的数据结构
!祖先结点->从一个结点走到根结点经过的所有结点
!数的路径只能从小往下走
!结点的高度->从下往上数 !注意是高度,不是深度/层次!
*/
/*树的性质
1.结点数=总度数+1
2.度为m的树:结点最多有m个孩子,最少存在1个有m个孩子的结点,一定是非空树(至少有m+1个结点)
3.m叉树:结点最多有m个孩子,允许所有结点度<m,可以是空树
4.度为m的树和m叉树第i层都至多有m^(i-1)个结点,高度为h时,至多有m^h-1 / m-1 个结点
5.高度为h的m叉树至少有h个结点,度为m的树至少有h+m-1个结点
!6.具有n个结点的m叉树的最小高度为	logm(n(m-1)+1)向上取整	h-1<logm(n(m-1)+1)<=h
*/
/*树的遍历
先根遍历=二叉树先序遍历
后根遍历=二叉树中序遍历
层次遍历
*/
/*森林的遍历
先序遍历=依次对子树先根遍历
中序遍历=依次对子树后根遍历
*/
/*二叉树的基本概念(可以是空二叉树)
注意:左右子树不能颠倒,是有序树
!满二叉树:结点数一定等于2^h-1
	只有最后一层有叶子结点!不存在度为1的结点!
	!左孩子编号是2i,右孩子是2i+1,父节点如果有就是i/2
!完全二叉树:结点编号与满二叉树一一对应(空树是)
	只有最后两层有叶子结点!最多只有一个度为1的结点->!所有如果存在一个结点有一个孩子,一定是左孩子!
	!如果结点存在,则编号规则同上
	!编号<=n/2为分支结点,i>n/2为叶子结点
!二叉排序树:(可以空)
!平衡二叉树:任何一个结点的左右子树深度之差不超过1的二叉排序数
*/
/*二叉树的性质
1.非空二叉树中,n0=n2+1,即叶子结点比二分支结点多一个
2.第i层最多有多少个结点
3.高度为h的二叉树最多有多少个结点
完全二叉树的高度为	log2(n+1)向上取整	or	log2n向下取整+1
完全二叉树n1=0或1,n0+n2一定是奇数!!!
*/
//二叉树的顺序存储->只适合存储完全二叉树
struct TreeNode {
	ElemType data;
	bool isEmpty;
};
TreeNode t[MaxSize];//t[0]空缺,需要初始化所有的isEmpty
//二叉树的链式存储 有2n的指针域,其中n+1为空指针域(只有左右孩子指针时)
typedef struct BiTNode {
	ElemType data;
	struct BiTNode *lchild, *rchild;
	struct BiTNode *parent;
	int ltag, rtag;
}BiTNode, *BiTree, ThreadNode, *ThreadTree;
BiTree T = NULL;
//先序遍历
void PreOrder(BiTree T) {
	if (T != NULL) {
		printf("%d\t", T->data);
		PreOrder(T->lchild);
		PreOrder(T->rchild);
	}
}
//中序遍历
void InOrder(BiTree T) {
	if (T != NULL) {
		InOrder(T->lchild);
		printf("%d\t", T->data);
		InOrder(T->rchild);
	}
}
//后序遍历
void PostOrder(BiTree T) {
	if (T != NULL) {
		PostOrder(T->lchild);
		PostOrder(T->rchild);
		printf("%d\t", T->data);
	}
}
//求树的深度
int treeDepth(BiTree T) {
	if (T == NULL) return 0;
	int l = treeDepth(T->lchild);
	int r = treeDepth(T->rchild);
	return l > r ? l + 1 : r + 1;
}
//层序遍历
void LevelOrder(BiTree T) {
	queue<BiTNode*> q;
	if (T != NULL) {
		printf("%d\t", T->data);
		q.push(T);
	}
	while (!q.empty()) {
		BiTNode* t = q.front();
		q.pop();
		if (t->lchild != NULL) {
			printf("%d\t", t->lchild->data);
			q.push(t->lchild);
		}
		if (t->rchild != NULL) {
			printf("%d\t", t->rchild->data);
			q.push(t->rchild);
		}
	}
}
//中序线索化
ThreadNode *pre = NULL;
void visit(ThreadNode *q) {
	if (q->lchild == NULL) {
		q->lchild = pre;
		q->ltag = 1;
	}
	if (pre != NULL && pre->rchild == NULL) {
		pre->rchild = q;
		pre->rtag = 1;
	}
	pre = q;
}
void InThread(ThreadTree T) {
	if (T != NULL) {
		InThread(T->lchild);
		visit(T);
		InThread(T->rchild);
	}
}
void CreateInThread(ThreadTree T) {
	pre = NULL;
	if (T != NULL) {//必须判断!如果为空就不存在pre->rchild
		InThread(T);
		if (pre->rchild == NULL)
			pre->rtag = 1;
	}
}
//先序线索化
void PreThread(ThreadTree T) {
	if (T != NULL) {
		visit(T);
		if (T->ltag == 0)//!!!注意!!!
			PreThread(T->lchild);
		if (T->rtag == 0)
			PreThread(T->rchild);
	}
}
void CreatePreThread(ThreadTree T) {
	pre = NULL;
	if (T != NULL) {
		PreThread(T);
		if (pre->rchild == NULL)
			pre->rtag = 1;
	}
}
//后序线索化
void PostThread(ThreadTree T) {
	if (T != NULL) {
		PostThread(T->lchild);
		PostThread(T->rchild);
		visit(T);
	}
}
void CreatePostThread(ThreadTree T) {
	pre = NULL;
	if (T != NULL) {
		PostThread(T);
		if (pre->rchild == NULL)//只有后序不可以省略
			pre->rtag = 1;
	}
}
//输出中序线索二叉树
void OutInThread(ThreadTree T) {
	if (T == NULL)return;
	while (T->ltag == 0)
		T = T->lchild;
	while (T != NULL) {//注意是T不是T的孩子!
		printf("%d\t", T->data);
		if (T->rtag == 1)
			T = T->rchild;
		else {
			T = T->rchild;
			while (T->ltag == 0)
				T = T->lchild;
		}
	}
}
//逆序输出中序线索二叉树
void ReOutInThread(ThreadTree T) {
	if (T == NULL)return;
	while (T->rtag == 0)
		T = T->rchild;
	while (T != NULL) {
		printf("%d\t", T->data);
		if (T->ltag == 1)
			T = T->lchild;
		else {
			T = T->lchild;
			while (T->rtag == 0)
				T = T->rchild;
		}
	}
}
//输出先序线索二叉树
void OutPreThread(ThreadTree T) {
	while (T != NULL) {
		printf("%d\t", T->data);
		if (T->rtag == 1)
			T = T->rchild;
		else {
			if (T->ltag == 0) {
				T = T->lchild;
			}
			else
				T = T->rchild;
		}
	}
}
//根据父节点逆序输出先序线索二叉树
void ReOutPreThread(ThreadTree T) {
	if (T == NULL)return;
	while (T->ltag == 0 || T->rtag == 0) {
		if (T->rtag == 0)
			T = T->rchild;
		else if (T->ltag == 0)
			T = T->lchild;
	}
	while (T != NULL) {
		printf("%d\t", T->data);
		ThreadNode *q = T; _abs64			
	}
}
//根据父节点输出后序线索二叉树
void OutPostThread(ThreadTree T) {
	if (T == NULL)return;
	while (T->ltag == 0 || T->rtag == 0) {
		if (T->ltag == 0)
			T = T->lchild;
		else if (T->rtag == 0)
			T = T->rchild;
	}
	while (T != NULL) {
		printf("%d\t", T->data);
		ThreadNode *q = T;
		T = T->parent;
		if (T != NULL && T->ltag == 0 && q == T->lchild&&T->rtag == 0) {
			T = T->rchild;
			while (T->ltag == 0 || T->rtag == 0) {
				if (T->ltag == 0)
					T = T->lchild;
				else if (T->rtag == 0)
					T = T->rchild;
			}
		}
	}
}
//逆序输出后序线索二叉树
void ReOutPostThread(ThreadTree T) {
	while (T != NULL) {
		printf("%d\t", T->data);
		if (T->ltag == 1)
			T = T->lchild;
		else {
			if (T->rtag == 0)
				T = T->rchild;
			else
				T = T->lchild;
		}
	}
}
//根据A[]创建二叉排序树
void CreateBST(BiTree &T, int A[], int n) {
	if (n > 0) {
		BiTNode *q = (BiTNode*)malloc(sizeof(BiTNode));
		q->data = A[0];
		q->lchild = q->rchild = q->parent = NULL;
		q->ltag = q->rtag = 0;
		T = q;
	}
	for (int i = 1; i < n; i++) {
		BiTree t = T;
		while (1) {
			if (A[i] > t->data) {
				if (t->rchild != NULL)
					t = t->rchild;
				else {
					BiTNode *q = (BiTNode*)malloc(sizeof(BiTNode));
					q->data = A[i];
					q->lchild = q->rchild = NULL;
					q->ltag = q->rtag = 0;
					t->rchild = q;
					q->parent = t;
					break;
				}
			}
			if (A[i] < t->data) {
				if (t->lchild != NULL)
					t = t->lchild;
				else {
					BiTNode *q = (BiTNode*)malloc(sizeof(BiTNode));
					q->data = A[i];
					q->lchild = q->rchild = NULL;
					q->ltag = q->rtag = 0;
					t->lchild = q;
					q->parent = t;
					break;
				}
			}
		}
	}
}
/*哈夫曼树
结点的带权路径长度:从树的根到该结点的路径长度(经过的边数)与该结点上权值的乘积
树的带权路径长度:树中所有叶结点的带权路径长度之和(WPL,Weighted Path Length)
哈夫曼树(最优二叉树):在含有n个带权叶结点的二叉树中,其中带权路劲长度(WPL)最小的二叉树
哈夫曼树的结点总数为2n-1,且并不存在度为1的结点
固定长度编码-每个字符用相等长度的二进制位表示
可变长度编码-允许对不同字符用不等长的二进制位表示
前缀编码-没有一个编码是另一个编码的前缀
*/
int main() {
	int A[] = { 16,8,32,1024,4,128,64,512,0,2,256 };
	int n = sizeof(A) / sizeof(A[0]);
	CreateBST(T, A, n);
	PreOrder(T); printf("前序遍历\n");
	InOrder(T); printf("中序遍历\n");
	PostOrder(T); printf("后序遍历\n");
	LevelOrder(T); printf("层次遍历\n");
	printf("树高:%d\n", treeDepth(T));

	printf("正在中序线索化……\n");
	CreateInThread(T);
	OutInThread(T); printf("输出中序线索二叉树\n");
	ReOutInThread(T); printf("逆序输出中序线索二叉树\n");

	T = NULL; CreateBST(T, A, n);
	printf("正在先序线索化……\n");
	CreatePreThread(T);
	OutPreThread(T); printf("输出先序线索二叉树\n");
	ReOutPreThread(T); printf("逆序输出先序线索二叉树\n");

	T = NULL; CreateBST(T, A, n);
	printf("正在后序线索化……\n");
	CreatePostThread(T);
	OutPostThread(T); printf("输出后序线索二叉树\n");
	ReOutPostThread(T); printf("逆序输出先序线索二叉树\n");
	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值