一篇关于二叉树的笔记。
- 广义表生成二叉树。
- 二叉树前、中、后序遍历递归实现。
- 二叉树前、中、后序遍历非递归实现。
- 二叉树层次遍历
- 二叉排序树(二叉搜索树)生成
- 中序线索二叉树声生成、遍历。
//
// main.cpp
// 二叉树前中后缀遍历之递归和非递归、层次遍历、中序线索二叉树建立、遍历
//
// Created by scnulpc on 2018/10/16.
// Copyright © 2018年 scnulpc. All rights reserved.
//
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
struct treeNode
{
char value;
int ltag;
int rtag;
treeNode* left;
treeNode* right;
treeNode(char a):value(a),ltag(0),rtag(0),left(NULL),right(NULL){}
};
struct node
{
int value;
node *left,*right;
node(int a):value(a),left(NULL),right(NULL){};
};
//广义表生成二叉树-非递归
treeNode* createTreeByList(char end)
{
char ch;
treeNode* root=NULL,* pre = NULL,*temp;
stack<treeNode*> *s = new stack<treeNode*>();
cin>>ch;
int flag=2;
while (true)
{
if (ch==end) break;
switch (ch) {
case '(':flag=0;s->push(pre);break;
case ',':flag=1;break;
case ')':flag=2;s->pop();break;
default:
if (flag==0)//'('
{ temp=s->top(); temp->left=new treeNode(ch);pre=temp->left;}
else if(flag==1)//','
{temp=s->top();temp->right=new treeNode(ch);pre=temp->right;}
else if (flag==2)//')'
{
if (root==NULL) {root=new treeNode(ch);pre=root;}
}
break;
}
cin>>ch;
}
return root;
}
//前序遍历-递归
void preOrder(treeNode*p)
{
if (p==NULL) return;
cout<<p->value<<" ";
preOrder(p->left);
preOrder(p->right);
}
//前序遍历-非递归
void preOrderND(treeNode*p)
{
stack<treeNode*> s;
s.push(p);
treeNode* temp;
while (!s.empty())
{
temp=s.top();
s.pop();
cout<<temp->value<<" ";
if (temp->right!=NULL) s.push(temp->right);
if (temp->left!=NULL) s.push(temp->left);
}
cout<<endl;
}
//中序遍历-递归
void midOeder(treeNode* p)
{
if (p==NULL) return;
midOeder(p->left);
cout<<p->value<<" ";
midOeder(p->right);
}
//中序遍历-非递归
//对于每个结点,先将最左子孙(如果存在的话),然后再次最左子孙,再次之
void midOrderND(treeNode*p)
{
if (p==NULL) return;
stack<treeNode*> s;
treeNode* current = p;
while ((!s.empty())||current!=NULL)
{
if (current!=NULL) {
s.push(current);
current=current->left;
}
else
{
current=s.top();
s.pop();
cout<<current->value<<" ";
current=current->right;
}
}
cout<<endl;
}
//后缀遍历-递归
void sufixOrder(treeNode* p)
{
if (p==NULL) return;
sufixOrder(p->left);
sufixOrder(p->right);
cout<<p->value<<" ";
}
//后缀遍历-非递归
//对于一个结点,先把它的左子树输出,回到它自己,再把它的右子树输出,再回到它自己,这时可以把它自己输出了
void sufixOrderND(treeNode* p)
{
stack<treeNode*> s;
int flag=0; //flag:0 表示从左子树中返回。 flag:1 表示从右子树中返回
//int move=1; //move:1 一棵子树还没生成。 move:0 已经生成一颗子树,说明可以直接出栈回退
treeNode* current=p;
while (!s.empty()||current!=NULL)
{
if (current!=NULL) {
s.push(current);
current=current->left;
flag=0;
}
else
{
if (flag)//从右子树中返回
{
current=s.top();s.pop();
cout<<current->value<<" "; //访问根结点
// 从根结点返回判断current结点是父结点的左孩子还是右孩子
if (s.empty()) break;
treeNode* temp = s.top();
if (current==temp->left) flag=0;
else if (current==temp->right) flag=1;
current=NULL;
}
else //从左子树中返回
{
current=s.top();
current=current->right;
flag=1;
}
}
}
cout<<endl;
}
void LayerPrint(treeNode* p)
{
queue<treeNode*> q;
q.push(p);
treeNode* current;
while (!q.empty())
{
current=q.front();
q.pop();
cout<<current->value<<" ";
if (current->left!=NULL) q.push(current->left);
if (current->right!=NULL) q.push(current->right);
}
cout<<endl;
}
void Insert(node*& p,int value) //在以p为根节点的线索二叉树中插入一个数value
{
if (p==NULL) {p=new node(value);return;}
if(p->value==value) return ;
if (value<p->value) Insert(p->left, value);
if (value>p->value) Insert(p->right, value);
}
node* createSearchBinaryTree(int a[],int length)
{
node* root =NULL;
for (int i=0; i<length; i++) {
Insert(root, a[i]);
}
return root;
}
void print(node *p)
{
if (p==NULL) return;
print(p->left);
cout<<p->value<<" ";
print(p->right);
}
//一般完全二叉树 生成 中序线索二叉树
treeNode* first(treeNode* p)//找到以结点p为根节点的子树在中序下的第一个结点
{
if (p==NULL) return p;
while (p->ltag==0) {
p=p->left;
}
return p;
}
treeNode* last(treeNode* p)//找到以结点p为根节点的树在中序下的最后一个结点
{
if (p==NULL) return NULL;
while (p->rtag==0) {
p=p->right;
}
return p;
}
void createMidThreadBinaryTree(treeNode* p,treeNode* &pre) //线索化以p为根的子树 pre: p的在中序遍历下的前驱
{
if(p==NULL)return;
createMidThreadBinaryTree(p->left, pre);
if (p->left==NULL&&p->ltag==0) {p->left=pre;p->ltag=1;} //线索化p的前驱
if(pre!=NULL&&pre->right==NULL){pre->right=p;pre->rtag=1;} //线索化前驱pre的后继
pre=p;
createMidThreadBinaryTree(p->right, pre);
}
void createMidThreadBinaryTree(treeNode* p)
{
treeNode* t = NULL;
createMidThreadBinaryTree(p, t);
if (p==NULL) return;
treeNode* temp = p; //别忘了最后一个结点的后驱置空
while (temp->right!=NULL) {
temp=temp->right;
}
temp->rtag=1;
}
//遍历中序线索二叉树
treeNode* Next(treeNode* p)//找到结点P的后驱
{
if (p==NULL) return NULL;
if (p->rtag==1) return p->right;
else return first(p->right);
}
void printMidThreadBinaryTree(treeNode* p)
{
treeNode* one = first(p);
if (one==NULL) return;
cout<<one->value<<" ";
treeNode* next = Next(one);
while (next!=NULL) {
cout<<next->value<<" ";
next = Next(next);
}
cout<<endl;
}
//A(B(C(D,E)),F(G,H))#
int main(int argc, const char * argv[])
{
treeNode* head = NULL;
cout<<"输入广义表,以#结束"<<endl;
head=createTreeByList('#');
cout<<"前序遍历"<<endl;
preOrder(head);
cout<<endl;
preOrderND(head);
cout<<"中序遍历"<<endl;
midOeder(head);
cout<<endl;
midOrderND(head);
cout<<"后缀遍历"<<endl;
sufixOrder(head);
cout<<endl;
sufixOrderND(head);
cout<<"层次遍历"<<endl;
LayerPrint(head);
cout<<"生成二叉搜索树"<<endl;
int a[] = {2,3,7,8,9,5,1,4,0,13,7,8,9,23};
node * root = createSearchBinaryTree(a,14);
print(root);
cout<<endl;
cout<<"生成中序线索二叉树"<<endl;
createMidThreadBinaryTree(head);
cout<<"遍历中序线索二叉树"<<endl;
printMidThreadBinaryTree(head);
return 0;
}