C/C++二叉树

一、 二叉树的层次遍历

设计一个类来描述节点

struct TreeNode {
	//数据域
	int data;
	//指针域
	TreeNode* leftchild;
	TreeNode* rightchile;
};

层次建树
引入队列
逻辑:
初始时,TreeNode* root 为NULL,创建一个队列,这个队列用来保存将要插入的位置
读取字符,非#:根据字符,创建一个TreeNode 对象,把创建的TreeNode对象的左右孩子入队,判断root是否为空,直接让root指向新的TreeNode对象即可,访问队列,得到本次插入的位置,插入读取字符
读取字符,是#:访问队列,找到本次插入的位置,置为空指针,出队

#include<cstdio>
#include<queue>
using namespace std;
struct TreeNode {
	//数据域
	int data;
	//指针域
	TreeNode* leftchild;
	TreeNode* rightchild;
};
struct QueueNode {
	TreeNode* parent;
	bool isLeft;
};
//因为插入操作会修改root(main)的指向,所以要使用引用
void insertTreeNode(TreeNode* &root,queue<QueueNode*> &myQueue,char data ) {
	if (data != '#') {
		//创建二叉树节点,因为是在被调用函数内创建,所以要申请堆空间
		TreeNode* pTreeNode = new TreeNode;
		(*pTreeNode).data = data;
		//入队
		QueueNode* pQueueNode = new QueueNode;
		pQueueNode->parent = pTreeNode;
		pQueueNode->isLeft = false;
		//插入操作
		if (root == NULL) {
			//说明插入的是第一个节点
			root = pTreeNode;
		}
		else {
			//说明插入的不是根
			QueueNode* pParent = myQueue.front();
			if (pParent->isLeft == false) {
				pParent->parent->leftchild = pTreeNode;
				pParent->isLeft = true;
			}
			else {
				pParent->parent->rightchild = pTreeNode;
				myQueue.pop();//出队
				delete pParent;//出队后,就无用了
			}
		}
	}
	else {
		//#
		if (root != NULL) {
			QueueNode* pParent = myQueue.front();
			if (pParent->isLeft == false) {
				pParent->parent->leftchild = NULL;
				pParent->isLeft = true;
			}
			else {
				pParent->parent->rightchild = NULL;
				myQueue.pop();
				delete pParent;//出队后,就无用了

			}
		}
	
	}
}
int main() {
	TreeNode *root=NULL;//root用来指向根节点
	char charList[] = "abc##de#g##f###";
	queue<QueueNode*>myQueue;
	for (int i = 0; charList[i] != '\0'; i++) {
		insertTreeNode(root,myQueue,charList[i]);
	}

}

** 二、二叉树的遍历**

void LevelOrder(TreeNode* root) {
	queue<TreeNode*>pos;//存储将要访问的结点的地址
	pos.push(root);
	while (pos.empty()==false) {
		TreeNode* pCur = pos.front();//找到队首
		pos.pop();//出队
		//访问队首
		printf("%c", pCur->data);
		if (pCur->leftchild != NULL) {
			pos.push(pCur->leftchild);
		}
		if (pCur->rightchild != NULL) {
			pos.push(pCur->rightchild);
		}
	}
}

三、二叉树的递归遍历

先序遍历

void PreOrder(TreeNode*root){
	if(root==NULL){
		return;
	}
	printf("%c",root->data);
	PreOrder(root->leftchild);
	PreOrder(root->rightchild);
}

中序遍历

void InOrder(TreeNode*root){
	if(root==NULL){
		return;
	}
	InOrder(root->leftchild);
	printf("%c",root->data);
	InOrder(root->rightchild);
}

后序遍历

void PostOrder(TreeNode*root){
	if(root==NULL){
		return;
	}
	PostOrder(root->leftchild);
	PostOrder(root->rightchild);
	printf("%c",root->data);
}

四、重建二叉树

根据先序遍历和中序遍历重建二叉树
步骤:
从先序中找到根
拿到这个根看中序——>找到根的左右子树

 #include<cstdio>
#include<string>
using namespace std;
struct TreeNode {
	char data;
	TreeNode* leftchild;
	TreeNode *rightchild;
};
TreeNode * rebuild(string preOrder, string inOrder) {
	if (preOrder.size() == 0) {
		return NULL;
	}
	else {
		char rootdata = preOrder[0];
		TreeNode* pNewNode = new TreeNode;
		pNewNode->data = rootdata;
		//拿根去切割中序
		int pos = inOrder.find(rootdata);
		pNewNode->leftchild=rebuild(preOrder.substr(1, pos),inOrder.substr(0,pos));
		pNewNode->rightchild = rebuild(preOrder.substr(pos + 1), inOrder.substr(pos + 1));
		return pNewNode;
	}

}
int main() {
	char preOrder[30];
	char inOrder[30];
	while (scanf("%s%s", preOrder, inOrder) != EOF) {
		TreeNode* root = rebuild(preOrder, inOrder);
	}
}

根据后序遍历和中序遍历重建二叉树
步骤:
从后序中先找到根
拿到这个根看中序——>找到根的左右子树

五、遍历二叉树

用先序序列构建二叉树,但是给出空结点信息
如:ab##cd#gf###e##

#include<cstdio>
#include<string>
using namespace std;
struct TreeNode {
	char data;
	TreeNode* leftchild;
	TreeNode *rightchild;
};
TreeNode *RecursiveBuildTree(int &i, string str) {
	//返回本棵子树的根节点的地址
	char c = str[i];
	++i;
	if (c == '#') {
		return NULL;
	}
	else {
		TreeNode* pNewNode = new TreeNode;
		pNewNode->data = c;
		pNewNode->leftchild = RecursiveBuildTree(i, str);
		pNewNode->rightchild = RecursiveBuildTree(i, str);
		return pNewNode;
	}

}
int main() {
	char str[1000];
	while (scanf("%s", str) != EOF) {
		int i = 0;
		TreeNode* root = RecursiveBuildTree(i, str);
	}
	 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值