数据结构——树、树的遍历

本文探讨了数据结构中的树形结构,重点讲解了二叉树、二叉排序树和线索树的概念,并详细阐述了如何实现树的遍历操作。
摘要由CSDN通过智能技术生成

二叉树、二叉排序树、线索树、树的遍历实现


/*
 *	二叉树
 */
typedef struct BiTNode{
	ElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

// 递归先序遍历
void PreOrder(BiTree T) {
	if(T!=NULL) {
		visit(T);
		PreOrder(T->lchild);
		PreOrder(T->rchild);
	}
}

// 非递归先序遍历
void PreOrderNonRec(BiTree T) {
	if(T!=NULL) {
		InitStack(S);
		BiTree p = T;
		while(p||!IsEmpty(S)) {
			if(p) {
				visit(p);
				Push(S,p);
				p = p->lchild;
			} else {
				Pop(S,p);
				p = p->rchild;
			}
			
		}
	}
}

// 递归中序遍历
void InOrder(BiTree T) {
	if(T!=NULL) {
		InOrder(T->lchild);
		visit(T);
		InOrder(T->rchild);
	}
}

// 非递归中序遍历
void InOrderNonRec(BiTree T) {
	if(T!=NULL) {
		InitStack(S);
		BiTree p = T;
		while(p||!IsEmpty(S)) {
			if(p != NULL) {
				Push(S,p);
				p = p->lchild;
			} else {
				Pop(S,p);
				visit(p);
				p = p->rchild;
			}

		}
	}
}

// 递归后续遍历
void PostOrder(BiTree T) {
	if(T!=NULL) {
		PostOrder(T->lchild);
		PostOrder(T->rchild);
		visit(T);
	}
}

// 非递归后续遍历
void PostOrderNonRec(BiTree T) {
	if(T!=NULL) {
		InitStack(S);
		BiTree p,r;
		p = T;
		r = NULL;
		while(p||!IsEmpty(S)) {
			if(p!=NULL) {
				Push(S,p);
				p = p->lchild;
			} else {
				GetTop(S,p);
				if(p->rchild!=NULL && p->rchild!=r) {  //右子树存在且未被访问过
					p = p->rchild;
					Push(S,p);
					p = p->lchild;	//再转向最左
				} else {
					Pop(S,p);
					visit(p);
					r = p;	//记录最近访问过的结点
					p = NULL;
				}
			}
		}
	}
}

// 层序遍历
void leverOrder(BiTree T) {
	if(T==NULL)
		return;
	InitQueue(Q);
	BiTree p = T;
	EnQueue(Q,p);
	while(!IsEmpty(Q)) {
		DeQueue(Q,p);
		visit(p);
		if(p->lchild!=NULL)
			EnQueue(Q,p->lchild);
		if(p->rchild!=NULL) 
			EnQueue(Q,p->rchild);
	}
}

// 自下而上、从右到左遍历二叉树
void R_levelOrder(BiTree T) {
	if(T==NULL)
		return;
	InitQueue(Q);
	InitStack(S);
	BiTree p = T;
	Push(S,p);
	while(!IsEmpty(Q)) {
		DeQueue(Q,p);
		Push(S,p);
		if(p->lchild!=NULL)
			EnQueue(Q,p->lchild);
		if(p->rchild!=NULL) 
			EnQueue(Q,p->rchild);
	}
	while(!IsEmpty(S)) {
		Pop(S,p);
		visit(p);
	}
}

// 求二叉树高度
int Height(BiTree T) {
	if(T==NULL)
		return 0;
	ldep = Height(T->lchild);	// 左子树高度
	rdep = Height(T->rchild);	// 右子树高度
	if(ldep > rdep) 
		return ldep+1;
	else 
		return rdep+1;
}

// 计算二叉树中所有双分支结点个数
int DsonNodes(BiTree T) {
	if(T==NULL)
		return 0;
	if(T->lchild!=NULL && T->rchild!=NULL)
		return DsonNodes(T->lchild)+DsonNodes(T->rchild)+1;
	return DsonNodes(T->lchild)+DsonNodes(T->rchild);
}

// 交换二叉树所有结点的左右子树
void ExchangeBiTreeChild(BiTree T) {
	if(T==NULL)
		return;
	ExchangeBiTreeChild(T->lchild);
	ExchangeBiTreeChild(T->rchild);
	BiTNode p;
	p = T->lchild;
	T->lchild = T->rchild;
	T->rchild = p;
	p = NULL;
}

// 判断是否二叉排序树
void Judge_AVL(BiTree T, int &balance, int &h) {
	if(T==NULL) {
		h = 0;
		balance = 1;
	}
	else if(T->lchild==NULL&&T->rchild==NULL) {
		h = 1;
		balance = 1;
	} else {
		Judge_AVL(T->lchild, bl, hl);
		Judge_AVL(T->rchild, br, hr);
		h = (hl>hr?hl:hr)+1;
		if(abs(hl-hr)<2) 
			balance = bl&&br;
		else 
			balance = 0;
	}
}

// 求二叉排序树最小/最大值结点
BiTNode *MinNode(BiTNode T) {
	while(T->lchild!=NULL)
		T = T->lchild;
	return T;

	// while(T->rchild!=NULL)
	// 	T = T->rchild;
	// return T;
}

// 统计二叉树中度为0的结点个数
int countTreeNode_0(BiTree T) {
	if(T==NULL)
		return 0;
	int lc,rc;
	lc = countTreeNode_0(T->lchild);
	rc = countTreeNode_0(T->rchild);
	if(lc==0 && rc==0)
		return 1;
	return lc+rc;
}

'<Mark>'
// 找到二叉排序树第k小的结点
BiTNode *KthNode(BiTNode T, int &k) {
	if(k<1||k>T->count)
		return NULL;
	if(T->lchild == NULL) {
		if(k==1)
			return T;
		else return KthNode(T->rchild, k-1);
	} else {
		if(T->lchild->count==k-1)
			return T;
		if(T->lchild->count>k-1)
			return KthNode(T->lchild,k);
		if(T->lchild->count<k-1)
			return KthNode(T->rchild,k-(T->lchild->count+1));
	}

}


/*
 *	线索树
 */
typedef struct ThreadNode {
	ElemType data;
	struct ThreadNode *lchild,*rchild;
	int ltag,rtag;
}ThreadNode, *ThreadTree;

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);	//递归线索化右子树
	}
}

// 主过程
void CreateInThread(ThreadTree T) {
	ThreadTree pre = NULL;
	if(T!=NULL) {
		InThread(T,pre);
		pre->rchild = NULL; //处理最后一个结点
		pre->rtag = 1;
	}
}

// 求中序线索二叉树的第一个结点
ThreadNode *FirstNode(ThreadNode *p) {
	while(p->ltag==0)
		p = p->lchild;
	return p;
}

// 求中序线索二叉树下一个结点
ThreadNode *NextNode(ThreadNode *p) {
	if(p->rtag==0)
		return FirstNode(p->rchild);	// 指向右孩子时需要找到右孩子第一个最左的结点
	return p->rchild;
}

// 线索二叉树中序遍历
void Inorder(ThreadNode *T) {
	for(ThreadNode *p=FirstNode(T); p!=NULL; p=NextNode(T))
		visit(p);
}





 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值