一、 二叉树的层次遍历
设计一个类来描述节点
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);
}
}