C++实现二叉树及其线索化和遍历

/*
 * BiTree.h
 *
 *  Created on: Oct 17, 2015
 *      Author: chris
 */

#ifndef BITREE_H_
#define BITREE_H_

#include<iostream>

typedef int ElemType;

struct BTNode {
	ElemType data;
	BTNode *lchild, *rchild;
	BTNode *pre, *next;

	BTNode(): lchild(NULL), rchild(NULL),
			pre(NULL), next(NULL) {}
};

typedef BTNode* BiTree;

bool BiTreeCreate(BiTree & T);
void BiTreeDestroy(BiTree & T);

bool BiTreePreOrderTraverse(BiTree T, bool (*visit)(ElemType &));
bool BiTreeInOrderTraverse(BiTree T, bool (*visit)(ElemType &));
bool BiTreePostOrderTraverse(BiTree T, bool (*visit)(ElemType &));
bool BiTreeLevelOrderTraverse(BiTree T, bool (*visit)(ElemType &));

void BiTreePreOrderThreading(BiTree T);
void BiTreeInOrderThreading(BiTree T);
void BiTreePostOrderThreading(BiTree T);
void BiTreeLevelOrderThreading(BiTree T);

void BiTreeWalkThrough(BiTree T);
void BiTreeDisplay(BiTree T);

#endif /* BITREE_H_ */



/*
 * BiTree.cpp
 *
 *  Created on: Oct 17, 2015
 *      Author: chris
 */

#include<iostream>
#include"BiTree.h"

using namespace std;

bool BiTreeCreate(BiTree & T)
{
	static int depth = 0;

	if(!T)  {
		T = new BTNode;
		if(!T) return false;

		cout << "Now: " << (void*)&T << ";  Depth: " << depth << ";  Value: " << T->data << endl;
    	cout << "Left: " << (void*)T->lchild << ";  Right: " << (void*)T->rchild << endl;

		cout << "Value: "; cout.flush();
		cin >> T->data;
	}

	++depth;
	while(true) {
	    int choice = 0;
	    do{
	    	cout << "Now: " << (void*)&T << ";  Depth: " << depth << ";  Value: " << T->data << endl;
	    	cout << "Left: " << (void*)T->lchild << ";  Right: " << (void*)T->rchild << endl;
		    cout << "1: lchild; 2: rchild; 3: back" << endl;
		    cin >> choice;

		    if( choice >= 1 && choice <= 3);
		    	break;
	    }while(true);

	    if(choice == 3)
	    	break;
	    else if(choice == 1) {
	    	BiTreeCreate(T->lchild);
	    }
	    else if(choice == 2) {
	    	BiTreeCreate(T->rchild);
	    }//endif
	}//endw

	--depth;
	return true;
}

void BiTreeDestroy(BiTree & T)
{
	if(T->lchild)
		BiTreeDestroy(T->lchild);
	if(T->rchild)
		BiTreeDestroy(T->rchild);
	delete T;
	T = NULL;
}

bool BiTreePreOrderTraverse(BiTree T, bool (*visit)(ElemType &))
{
	if(!T) return true;
	if(visit(T->data))
		if(BiTreePreOrderTraverse(T, visit))
			if(BiTreePreOrderTraverse(T, visit))
				return true;
	return false;
}

bool BiTreeInOrderTraverse(BiTree T, bool (*visit)(ElemType &))
{
	if(!T) return true;
	if(BiTreeInOrderTraverse(T, visit))
		if(visit(T->data))
			if(BiTreeInOrderTraverse(T, visit))
				return true;
	return false;
}

bool BiTreePostOrderTraverse(BiTree T, bool (*visit)(ElemType &))
{
	if(!T) return true;
	if(BiTreePostOrderTraverse(T, visit))
		if(BiTreePostOrderTraverse(T, visit))
			if(visit(T->data))
				return true;
	return false;
}

bool BiTreeLevelOrderTraverse(BiTree T, bool (*visit)(ElemType &))
{   // bfs
	if(!T) return true;

    const int MAXQSIZ = 512;
    BTNode* queue[MAXQSIZ];
    int front = 0, rear = 0;

    queue[rear++] = T;
    while(front != rear) {
    	//dequeue
    	BTNode * pcur = queue[front];
	    front = (front + 1)%MAXQSIZ;

	    if(!visit(pcur->data))
	    	return false;

	    //enqueue
	    if(pcur->lchild) {
	    	if((rear + 1) % MAXQSIZ == front) {
	    		cerr << "Overflow" << endl;
	    		return false;
	    	}
	    	queue[rear] = pcur->lchild;
	    	rear = (rear + 1) % MAXQSIZ;
	    }
	    if(pcur->rchild) {
	    	if((rear + 1) % MAXQSIZ == front) {
	    		cerr << "Overflow" << endl;
	    		return false;
	    	}
	    	queue[rear] = pcur->rchild;
	    	rear = (rear + 1) % MAXQSIZ;
	    }
    }//endw
}

void BiTreePreOrderThreading(BiTree T)
{
	if(!T) return;
	static int depth = 0;
	static BTNode* pre = NULL;

	++depth;
	if(pre) {
		pre->next = T;
		T->pre = pre;
	}
	pre = T;
	BiTreePreOrderThreading(T->lchild);
	BiTreePreOrderThreading(T->rchild);

	--depth;
	if(depth == 0) {
		T->pre = pre;
		pre->next = T;

		pre = NULL;
	}
}

void BiTreeInOrderThreading(BiTree T)
{
	if(!T) return;
	static int depth = 0;
	static BTNode* pre = NULL;

	++depth;
	BiTreeInOrderThreading(T->lchild);
	if(pre) {
		pre->next = T;
		T->pre = pre;
	}
	pre = T;
	BiTreeInOrderThreading(T->rchild);
	--depth;

	if(depth == 0) {
		BTNode *pcur = T;
		while(pcur->lchild)
			pcur = pcur->lchild;
		pcur->pre = pre;
		pre->next = pcur;

		pre = NULL;
	}
}

void BiTreePostOrderThreading(BiTree T)
{
	if(!T) return;
	static int depth = 0;
	static BTNode* pre = NULL;

	++depth;
	BiTreePostOrderThreading(T->lchild);
	BiTreePostOrderThreading(T->rchild);
	if(pre) {
		pre->next = T;
		T->pre = pre;
	}
	pre = T;
	--depth;

	if(depth == 0) {
		BTNode * pcur = T;
		while(pcur->lchild)
			pcur = pcur->lchild;
		pcur->pre = pre;
		pre->next = pcur;

		pre = NULL;
	}
}

void BiTreeLevelOrderThreading(BiTree T)
{
	if(!T) return;

	BTNode * pre = NULL;

	const int MAXQSIZ = 512;
	BTNode* queue[MAXQSIZ];
	int front = 0, rear = 0;

	queue[rear++] = T;
	while(front != rear) {
   	    //dequeue
   	    BTNode * pcur = queue[front];
        front = (front + 1)%MAXQSIZ;

        if(pre) {
    	    pre->next = pcur;
    	    pcur->pre = pre;
        }
        pre = pcur;

        //enqueue
        if(pcur->lchild) {
    	    if((rear + 1) % MAXQSIZ == front) {
    		    cerr << "Overflow" << endl;
    		    return;
    	    }

    	    queue[rear] = pcur->lchild;
    	    rear = (rear + 1) % MAXQSIZ;
        }
        if(pcur->rchild) {
    	    if((rear + 1) % MAXQSIZ == front) {
    		    cerr << "Overflow" << endl;
    		    return;
    	    }
            queue[rear] = pcur->rchild;
	    	rear = (rear + 1) % MAXQSIZ;
	    }
    }//endw

	T->pre = pre;
	pre->next = T;
}

void BiTreeWalkThrough(BiTree T)
{
	if(!T) {
		cout << "Empty!" << endl;
		return;
	}

	BiTree subT = T;
	while(true) {
		cout << "Now: " << (void*)subT
				<< "; Data: " << subT->data << ";" << endl;
		cout << "Left: " << (void*)subT->lchild
				<< "; Right: " << (void*)subT->rchild << ";"
				<< " Pre: " << (void*)subT->pre << "; Next: " << (void*)subT->next << endl;

		int ans = 0;
		do{
		    cout << "1: to left; 2: to right; 3: to pre; 4: to next; 5: root; 6: stop" << endl;
		    cin >> ans;
		    if(ans >= 1 && ans <= 6)
		    	break;
		}while(true);

		if(ans == 1) {
			if(T->lchild)
				subT = subT->lchild;
			else
				cout << "Empty" << endl;
		}
		else if(ans == 2) {
			if(T->rchild)
				subT = subT->rchild;
			else
			    cout << "Empty" << endl;
		}
		else if(ans == 3) {
			if(T->pre)
				subT = subT->pre;
			else
				cout << "Empty" << endl;
		}
		else if(ans == 4) {
			if(T->next)
				subT = subT->next;
			else
				cout << "Empty" << endl;
		}
		else if(ans == 5){
			subT = T;
		}
		else
			break;
	}//endw
}

void BiTreeDisplay(BiTree T)
{
	if(!T) return;

	cout << " " << T->data;
	if(T->lchild || T->rchild)
	    cout << ":";
	else
		cout << " ";

	if(T->lchild) {
	    cout << "L(";
	    BiTreeDisplay(T->lchild);
	    cout << ")";
	}

	if(T->lchild && T->rchild)
		cout << "--";

	if(T->rchild) {
	    cout << "R(";
	    BiTreeDisplay(T->rchild);
	    cout << "); ";
	}

	cout.flush();
}





/*
 * Main.cpp
 *
 *  Created on: Oct 17, 2015
 *      Author: chris
 */

#include<iostream>
#include"BiTree.h"

using namespace std;

int main(void)
{
	BiTree bt = NULL;
	BiTreeCreate(bt);
	BiTreeDisplay(bt);
	cout << endl;

	cout << "PreOrder" << endl;
	BiTreePreOrderThreading(bt);
	BiTreeWalkThrough(bt);

	cout << "InOrder" << endl;
	BiTreeInOrderThreading(bt);
	BiTreeWalkThrough(bt);

	cout << "PostOrder" << endl;
	BiTreePostOrderThreading(bt);
	BiTreeWalkThrough(bt);

	cout << "LevelOrder" << endl;
	BiTreeLevelOrderThreading(bt);
	BiTreeWalkThrough(bt);

	BiTreeDestroy(bt);
	system("pause");
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
二叉树的中序线索化是指在二叉树的每个节点中,增加两个指针ltag和rtag,分别表示该节点的左子树指针和右子树指针是指向其前驱或后继节点的线索,而不是指向子树。通过线索化,可以在不使用递归和栈的情况下,完成二叉树的中序遍历实现中序线索化的核心思路是在中序遍历的过程中,记录前驱节点和后继节点,并将其指针修改为指向对应的节点。下面是一个简单的C++代码实现: ```C++ #include<iostream> using namespace std; struct TreeNode { int val; TreeNode* left; TreeNode* right; bool ltag; bool rtag; TreeNode(int x) : val(x), left(NULL), right(NULL), ltag(false), rtag(false) {} }; // 中序线索化 void InThread(TreeNode* root, TreeNode*& pre) { if (!root) return; InThread(root->left, pre); if (!root->left) { root->left = pre; root->ltag = true; } if (pre && !pre->right) { pre->right = root; pre->rtag = true; } pre = root; InThread(root->right, pre); } // 中序遍历 void InOrder(TreeNode* root) { if (!root) return; TreeNode* p = root; while (p->left) p = p->left; while (p) { cout << p->val << " "; if (p->rtag) p = p->right; else p = p->right->left; } } int main() { TreeNode* root = new TreeNode(1); root->left = new TreeNode(2); root->right = new TreeNode(3); root->left->left = new TreeNode(4); root->left->right = new TreeNode(5); root->right->left = new TreeNode(6); root->right->right = new TreeNode(7); TreeNode* pre = NULL; InThread(root, pre); InOrder(root); return 0; } ``` 在这个例子中,我们定义了一个结构体`TreeNode`来表示二叉树的节点。其中,`ltag`和`rtag`分别表示该节点的左子树指针和右子树指针是否是线索。在中序线索化的过程中,我们使用一个指针`pre`来记录前驱节点,以便修改指针的指向。在中序遍历时,我们从根节点开始,找到最左侧的节点,然后按照线索指针依次遍历每个节点,直到遍历完整棵树。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值