树和二叉树代码补充

  • 二叉树的顺序存储
#define MaxSize 100
struct TreeNode {
	ElemType value; //结点中的数据元素
	bool isEmpty;   //结点是否为空
};

TreeNode t[MaxSize];

for (int i = 0; i < MaxSize; i++) {
	t[i].isEmpty = true;
}
  • 二叉树的链式存储
struct ElemType {
	int value;
};

typedef struct BiTNode {
	ElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

//定义一棵空树
BiTree root = NULL;

//插入根节点
root = (BiTree)malloc(sizeof(BiTNode));
root->data. = { 1 };
root->lchild = NULL;
root->rchild = NULL;

//插入新结点
BiTNode * p = (BiTNode *)malloc(sizeof(BiTNode));
p->data = { 2 };
p->lchild = NULL;
p->rchild = NULL;
root->lchild = p;  //作为根节点的左孩子
  • 求树的深度
int treeDepth(BiTree T) {
	if (T == NULL) {
		return 0;
	}
	else {
		int l = treeDepth(T->lchild);
		int r = treeDepth(T->rchild);
		//树的深度=Max(左子树深度,右子树深度)+1
		return l > r ? l + 1 : r + 1;
	}
}
  • 层序遍历
//层序遍历
void LevelOrder(BiTree T) {
	LinkQueue Q;
	InitQueue(Q);   //初始化辅助队列
	BiTree p;
	EnQueue(Q, T);  //将根结点入队
	while (!IsEmpty(Q)) { //队列不空则循环
		DeQueue(Q,p);    //队头结点出队
		visit(p);         //访问出队结点
		if (p->lchild != NULL)
			EnQueue(Q, p->lchild); //左孩子入队
		if (p->rchild != NULL)
			EnQueue(Q, p->rchild); //右孩子入队
	}
}
  • 二叉树的链式存储
//二叉树的结点(链式存储)
typedef struct BiTNode {
	char data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

//链式队列结点
typedef struct LinkNode {
	BiTNode * data;
	struct LinkNode *next;
}LinkNode;

typedef struct {
	LinkNode *front, *rear;  //队头队尾
}LinkQueue;
  • 孩子表示法(顺序+链式存储)
struct CTNode {
	int child;  //孩子结点在数组中的位置
	struct CTNode *next; //下一个孩子
};

typedef struct {
	ElemType data;
	struct CTNode *firstChild; //第一个孩子
} CTBox;

typedef struct {
	CTBox nodes[MAX_ TREE_ SIZE];
	int n, r;  //结点数和根的位置
} CTree;
  • 中序线索化
//线索二叉树结点
typedef struct ThreadNode {
	ElemType data;
	struct ThreadNode *lchild, *rchild;
	int ltag, rtag;   //左、右线索标志
}ThreadNode, *ThreadTree;

//中序遍历二叉树,一边遍历一边线索化
void InThread(ThreadTree T) {
	if (T != NULL) {
		InThread(T->lchild); //中序遍历左子树
		visit(T);            //访问根节点
		InThread(T->rchild); //中序遍历右子树
	}
}
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;
}

//中序线索化二叉树T
void CreateInThread(ThreadTree T) {
	pre = NULL;        //pre初始为NULL
	if (T != NULL) {   //非空二叉树才能线索化
		InThread(T);   //中序线索化二叉树
		if (pre->rchild == NULL)
			pre->rtag = 1;  //处理遍历的最后一个结点
	}
}

//全局变量pre,指向当前访问结点的前驱
ThreadNode *pre=NULL;
//中序线索化(王道版)
void InThread(ThreadTree p, ThreadTree &pre) {
	if (p != NULL) {
		InThread(p->lchild, pre); //递归, 线索化左子树
		if (p->lchild == NULL) {  //左子树为空,建立前驱线索
			p->lchild=pre;
			p->ltag = 1;
		}
		if (pre != NULL && pre->rchild == NULL) {
			pre->rchild = p; //建立前驱结点的后继线索
			pre->rtag = 1;
		}
		pre = p;  //标记当前结点成为刚刚访问过的结点
		InThread(p->rchild, pre); //递归,线索化右子树
	}//if(p!=NULL)
}
//中序线索化二叉树T
void CreateInThread(ThreadTree T) {
	ThreadTree pre = NULL;
	if (T != NULL) {        //非空二叉树,线索化
		InThread(T, pre);   //线索化二叉树
		pre->rchild = NULL; //处理遍历的最后一个结点
		pre->rtag = 1;
	}
}
  • 先序线索化
//先序遍历二叉树,一边遍历一边线索化
void PreThread(ThreadTree T) {
	if (T != NULL) {
		visit(T);          //先处理根节点
	    if (T->ltag == 0)  //lchild不是前驱线索,避免爱的魔力转圈圈
		    PreThread(T->lchild);
		PreThread(T->rchild);
	}
}
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;
}

//全局变量pre,指向当前访问结点的前驱
ThreadNode *pre = NULL;
//先序线索化(王道版)
void PreThread(ThreadTree p, ThreadTree &pre) {
	if (p != NULL) {
		if (p->lchild == NULL) { //左子树为空,建立前驱线索
			p->lchild = pre;
			p->ltag = 1;
		}
	if (pre != NULL && pre->rchild == NULL) {
		pre->rchild = p;  //建立前驱结点的后继线索
		pre->rtag = 1; .
		pre = p;   //标记当前结点成为刚刚访问过的结点
		if (p->ltag == 0)
			InThread(p->lchild, pre); //递归,线索化左子树
		InThread(p->rchild, pre);     //递归,线索化右子树
	}//if(p!=NULL)
}

//先序线索化二叉树T
void CreatePreThread(ThreadTree T) {
	ThreadTree pre = NULL;
	if (T != NULL) {
		//非空二叉树,线索化
		PreThread(T, pre);
		//线索化二叉树
		if (pre->rchild == NULL) //处理遍历的最后一 个结点
			pre->rtag = 1;
	}
}
  • 后序线索化
//全局变量pre,指向当前访问结点的前驱
ThreadNode *pre = NULL;

//后序线索化二叉树T
void CreatePostThread(ThreadTree T) {
	pre = NULL;       //pre初始为NULL
	if (T != NULL) {  //非空二叉树才能线索化
		InThread(T);  //中序线索化二叉树
		if (pre->rchild == NULL)
			pre->rtag = 1; //处理遍历的最后一个结点
	}
}

//后遍历二叉树,一边遍历一边线索化
void PostThread(ThreadTree T) {
	if (T!= NULL) {
		PostThread(T->lchild);  //后序遍历左子树
		PostThread(T->rchild);  //后序遍历右子树
		visit(T);  //访问根节点
	}
}
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 PostThread(ThreadTree p, ThreadTree &pre) {
	if (p != NULL) {
		InThread(p->lchild, pre);   //递归,线索化左子树
		InThread(p->rchild, pre);	//递归,线索化右子树
		if (p->lchild == NULL) {	//左子树为空,建立前驱线索
			p->lchild = pre;
			p->ltag = 1; .
		}
		if (pre!= NULL && pre->rchild == NULL) {
			pre->rchild = p; //建立前驱结点的后继线索
			pre->rtag = 1;
		}
		pre = p;  //标记当前结点成为刚刚访问过的结点
	} //if(p!=NULL)
}

//后序线索化二叉树T
void CreatePostThread(ThreadTree T) {
	ThreadTree pre = NULL;
	if (T != NULL) {        //非空二叉树,线索化
		PostThread(T, pre); //线索化二叉树
		if (pre->rchild == NULL) //处理遍历的最后一 个结点
			pre->rtag = 1;
	}
}
  • 中序遍历的后继结点和前驱结点
// 找到以p为根的子树中,第一个被中序遍历的结点 
ThreadNode* FirstNode(ThreadNode *p) 
{
	while(0 == p->ltag){ // 循环找到最左下结点 
		p = p->lchild;
	}
	return p;
}
// 中序线索二叉树中找到结点p的后继结点 
ThreadNode *NextNode(ThreadNode *p) 
{
	if(0 == p->rtag){
		// 返回右子树中的最左下结点 
		return FirstNode(p->rchild);
	}
	else{
		return p->rchild; // rtag == 1 直接返回后继线索 
	}
}
// 对中序线索二叉树进行中序遍历(非递归算法) 
void InOrder(ThreadNode *T) 
{
	for(ThreadNode *p = FirstNode(T); p != NULL; p = NextNode(p)){
		PrintNode(p);
	}
}



// 找到以p为根的子树中,最后一个被中序遍历的点 
ThreadNode* LastNode(ThreadNode *p)
{   
    // 循环找到最右下结点(不一定是叶节点) 
	while(0 == p->rtag){
		p = p->rchild;
	}
	return p; 
}
// 在中序线索二叉树中找到p的前驱 
ThreadNode* PreNode(ThreadNode *p)
{ 
	if(p->ltag == 0){  // 返回左子树中最右下结点 
		return LastNode(p->lchild);
	}
	else{
		return p->lchild;
	}
}
// 对线索二叉树逆向中序遍历 
void RevInOrder(ThreadNode *T)
{
	for(ThreadNode *p = LastNode(T); p != NULL; p = PreNode(p)){
		PrintNode(p);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值