线索二叉树的构造等问题

//线索二叉树的存储结构描述如下:
typedef struct ThreadNode {
 char data;//数据元素
 struct ThreadNode* lchild, * rchild;//左右孩子指针;
 int ltag, rtag;//左右线索标志  用0代表有孩子,
}ThreadNode,*ThreadTree;

1.中序线索二叉树的构造

ThreadNode* pre = NULL;//定义一个全局变量pre,用来表示访问结点的前一个结点
void visit(ThreadNode* q);

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;//用1代表是前驱,没有左孩子
 }
 if (pre!= NULL && pre->rchild ==NULL) {
  pre->rchild = q;//建立后继
  pre->rtag = 1;//用1代表是后继 没有有孩子。
 }
 pre = q;
}
//中序线索二叉树的构造;
void creatInThread(ThreadTree T) {
 if (T != NULL) {
  InThread(T);
  if (pre->rchild == NULL) {
   pre->rtag = 1;
  }
 }
}

2.前序线索二叉树的构造;

ThreadNode* pre = NULL;
void visit(ThreadNode* q);
//先序线索二叉树的构造;
void PreThread(ThreadTree T) {
 if (T!= NULL) {
  visit(T);
  if (T->ltag == 0) {
   PreThread(T->lchild);
  }
     PreThread(T->rchild);
 }
}

void visit(ThreadNode* q) {
 if (q->lchild == NULL) {
  q->lchild = pre;//建立前驱
  q->ltag = 1;//用1代表是前驱,没有左孩子
 }
 if (pre!= NULL && pre->rchild ==NULL) {
  pre->rchild = q;//建立后继
  pre->rtag = 1;//用1代表是后继 没有有孩子。
 }
 pre = q;
}
//前序线索二叉树的构造;
void creatPreThread(ThreadTree T) {
 if (T != NULL) {
  PreThread(T);
  if (pre->rchild == NULL) {
   pre->rtag = 1;
  }
 }
}

2.后序线索二叉树的构造;

//后续线索二叉树的构造;
void PostThread(ThreadTree T, ThreadTree &pre) {
	if (T!= NULL) {
		PostThread(T->lchild,pre);
	    PostThread(T->rchild,pre);
		if (T->lchild == NULL) {
			T->lchild = pre;//建立前驱
			T->ltag = 1;//用1代表是前驱,没有左孩子
		}
		if (pre != NULL && pre->rchild == NULL) {
			pre->rchild = T;//建立后继
			pre->rtag = 1;//用1代表是后继 没有有孩子。
		}
		pre = T;
	}
}
void creatPostThread(ThreadTree T) {
    ThreadTree pre=NULL:
	if (T != NULL) {
		PostThread(T,pre);
		if (pre->rchild == NULL) {
			pre->rtag = 1;
		}
	}
}
  1. 中序线索二叉树找前驱或后继等问题

//找到以p为根的子树中,第一个被中序遍历的结点;
ThreadNode* Firstnode(ThreadNode* p) {
	while (p->ltag == 0) {
		p = p->lchild;
	}
	return p;
}

//在中序线索二叉树中找到结点p的后继结点
ThreadNode* Nextnode(ThreadNode* p) {
	if (p->rtag == 1) {
		return  p->rchild;
	}
	else {
		return Firstnode(p->rchild);
	}
}

//在中序线索二叉树中进行中序遍历
void Inorder(ThreadNode* T) {
	/*for (ThreadNode* p = T; p != NULL; p = Nextnode(p)) {
		cout << p->data<<" ";
	}*/
	ThreadNode* p = T;
	while (p) {
		cout << p->data << " ";
		p = Nextnode(p);//寻找p的后继结点;
	}
}

//找到以p为根的子树中,最后一个被中序遍历的结点
ThreadNode* Lastnode(ThreadNode* p) {
	while (p->rtag == 0) {
		p = p->rchild;
	}
	return p;
}
//在中序线索二叉树中找到p节点的前驱节点
ThreadNode* Prenode(ThreadNode* p) {
	if (p->ltag == 1) {
		return  p->lchild;
	}
	else {
		return Lastnode(p->lchild);
	}
}
//对中序线索二叉树进行逆向中序遍历
void RevInorder(ThreadNode* T) {
	ThreadNode* p = T;
	while (p) {
		cout << p->data << " ";
		p = Prenode(p);//找到p的前驱节点
	}
}

5.先序线索二叉树问题

先序线索二叉树找先序后继;
在先序线索二叉树中找到指定节点*p
1:若p->rtag==1(表示p节点没有右孩子) 则next=p->rchild;
2.若p->rtag==0(表示p节点有有孩子)
    则next=左孩子或者右孩子(有左孩子则是左孩子,没有孩子则是右孩子)

先序线索二叉树找先序前驱:
由于它们的孩子肯定是后继节点
1.若能找到p的父节点,且p是左孩子,则父节点就是它的前序节点
2.若你能找到p的父节点,且左兄弟非空,且p是右孩子,则前驱节点是它的左兄弟子树中的最右下角的那个节点。
3.若能找到p的父节点,且左兄弟为空,且p是右孩子,则父节点就是它的前序节点。
4.若找不到p的父节点,则没有前驱节点。

6.后续线索二叉树问题

后序线索二叉树找后续前驱
在后序线索二叉树中找到指定节点*p
1.若p->ltag==1(表示p节点没有左孩子),则pre=p->lchild;
2.若p->ltag==0(表示p节点有左孩子),则:
   1.若右子树非空,则它的前驱节点就是它的右孩子;
   2.若右子树为空,则它的前驱节点就是它的左孩子;

后续线索二叉树找后续后继
在后序线索二叉树中找到指定节点*p
1.若p->rtag==1(表示p节点没有右孩子),则next=p->rchild;
2.若p->rtag==0(表示p节点有右孩子),则:
因为它们的孩子肯定是前驱节点
1.若能找到p的父节点,且p是左孩子,若右孩子非空,则它的后继节点在它的右兄弟树中。
2.若能找到p的父节点,且p是左孩子,若右孩子为空,则它的后继节点就是父节点。
3.若能找到p的父节点,且p是右孩子,则它的后继节点就是父节点。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值