1.二叉树的创建
*可以建立一颗不完全的二叉树
//创建
//广义表的方式 A(B(D,E),Q)#
void CreatBinTree( BinTreeNode<T>*& bt)
{
Refvalue = '#';
Stack<BinTreeNode<char>*> s;
bt = NULL; //把树置空
BinTreeNode<T>* p=bt, * t; int k;
char ch;
cin >> ch;
while (ch != Refvalue)
{
switch (ch)
{
case '(': s.Push(p); k = 1; break; //把左括号进栈,k=1,标志下一次创建左结点
case')': s.Pop(t); break;
case',': k = 2; break; //建立右子树
default:
p = new BinTreeNode<T>(ch);
if (bt == NULL) bt = p; //建立根结点
else if (k == 1) {
s.getTop(t); t->leftchild = p;
}
else
{
s.getTop(t), t->rightchild = p;
}
}
cin >> ch;
}
}
**前序遍历的创建(递归)
根左右的形式创建
BinTreeNode<T>* Creat(BinTreeNode<T>* bt)
{
char ch;
cin >> ch;
if (ch == '#')
{
bt = 0;
}
else {
bt = new BinTreeNode<T>;
bt->data = ch;
bt->leftchild = Creat(bt->leftchild);
bt->rightchild = Creat(bt->rightchild);
}
return bt;
}
用层次遍历的方式建立树(非递归)
//返回值:无
//函数功能:新建通讯录信息
//使用方法,层次遍历建立二叉树(这里是完全二叉树)
void studentDataBase::createTree()
{
queue<student*>stu;
root = new student;
cin >> *root;
stu.push(root);//根结点入队
while (!stu.empty())
{
student* temp = stu.front();//队首元素出队
stu.pop();
student* p = new student;//左子树
cin >> *p;
if (p->number[0]=='#')break;
temp->leftChild= p;
stu.push(p);
p = new student;//右子树
cin >> *p;
if (p->number[0] == '#')break;
temp->rightChild = p;
stu.push(p);
}
}
遍历二叉树
前,中,后序遍历
前序遍历(递归)
void preorder(BinTreeNode<T>* r)
{
if (r == NULL)
return;
else
{
cout << r->data<<" ";
preorder(r->leftchild);
preorder(r->rightchild);
}
}
前序遍历(非递归)
//非递归遍历,递归就是运行栈,所以现在人工实现栈
void preorder2() //传入根结点进入
{
Stack <BinTreeNode<T>*> s;
BinTreeNode<T>* t = root;
while (!s.Isempty() || t != 0)
{
while (t != 0) //先往左边,然后转到右边。
{
cout << t->data;
s.Push(t);
t = t->leftchild;
}
if(!s.Isempty())
{
s.Pop(t); t = t->rightchild;
}
}
}
中序遍历(非递归)
void inorder2()
{
Stack <BinTreeNode<T>*> s;
BinTreeNode<T>* t = root;
while (!s.Isempty() || t != 0)
{
while (t != 0) //先往左边,然后转到右边。
{
s.Push(t);
t = t->leftchild;
}
if (!s.Isempty())
{
s.Pop(t);
cout << t->data<<" ";
t = t->rightchild;
}
}
}
后序遍历非递归
这里考虑是后序,
根会经过两次
需要标记是第一次还是第二次
第一次则转向右结点(把根保存住)
第二次则直接输出,根已经弹出
void postorder2()
{ //左右根
Stack<stknode<T>> s; //存入栈中的元素,是树节点带左右返回标志
stknode<T> w;
BinTreeNode<T>* p = root;
do
{
while (p != 0)
{
w.ptr = p;
w.tag = 'L';
s.Push(w); //在第一次把根存入,后面存左节点
p = p->leftchild;
}
int continue1 = 1;
while (continue1 && !s.Isempty())
{
s.Pop(w); p = w.ptr;
switch (w.tag)
{
case 'L': w.tag = 'R'; s.Push(w);
continue1 = 0;
p = p->rightchild;
break;
case 'R': cout << p->data; break;
}
}
} while (!s.Isempty());
}
层次遍历
void levelorder(){
SeqQueue< BinTreeNode<T>*> s;
BinTreeNode<T>* p = root;
if(p!=0) s.EnQueue(p);
while (!s.IsEmpty())
{
s.DeQueue(p);
cout << p->data;
if (p->leftchild != 0 )
{
s.EnQueue(p->leftchild);
}
if (p->rightchild != 0)
{
s.EnQueue(p->rightchild);
}
}
cout << endl;
}
析构函数
void destroy(BinTreeNode<T>*& bt)
{
if (bt->leftchild != NULL&&bt->rightchild!=NULL)
{
destroy(bt->leftchild);
destroy(bt->rightchild);
delete bt;
}
};
以下是完整代码
#pragma once
#include"queue.h"
#include"stack.h"
#include <iostream>
using namespace std;
//创建树结点
template <class T>
struct BinTreeNode
{
T data;
BinTreeNode<T>* leftchild, *rightchild;
BinTreeNode(){};
BinTreeNode(T x, BinTreeNode<T>* l = NULL, BinTreeNode<T>* r = NULL)
{
data = x; leftchild = l; rightchild = r;
}
};
//用于后序遍历的非递归算法
template <class T>
struct stknode
{
BinTreeNode<T>* ptr;
char tag ;
stknode(BinTreeNode<T>* N = NULL):ptr(N),tag('L'){ }
};
template <class T>
class BinaryTree
{
public:
BinaryTree() { //CreatBinTree(root);
root = Creat(root);
};
~BinaryTree() { destroy(root);}
//递归遍历
void preorder(BinTreeNode<T>* r)
{
if (r == NULL)
return;
else
{
cout << r->data<<" ";
preorder(r->leftchild);
preorder(r->rightchild);
}
}
//非递归遍历,递归就是运行栈,所以现在人工实现栈
void preorder2() //传入根结点进入
{
Stack <BinTreeNode<T>*> s;
BinTreeNode<T>* t = root;
while (!s.Isempty() || t != 0)
{
while (t != 0) //先往左边,然后转到右边。
{
cout << t->data;
s.Push(t);
t = t->leftchild;
}
if(!s.Isempty())
{
s.Pop(t); t = t->rightchild;
}
}
}
void inorder(BinTreeNode<T>* r)
{
if (r == NULL)
return;
else
{
preorder(r->leftchild); //先左子树
cout << r->data << " "; //根
preorder(r->rightchild); //右
}
}
void inorder2()
{
Stack <BinTreeNode<T>*> s;
BinTreeNode<T>* t = root;
while (!s.Isempty() || t != 0)
{
while (t != 0) //先往左边,然后转到右边。
{
s.Push(t);
t = t->leftchild;
}
if (!s.Isempty())
{
s.Pop(t);
cout << t->data<<" ";
t = t->rightchild;
}
}
}
void postorder(BinTreeNode<T>* r)
{
if (r == NULL)
return;
else
{
preorder(r->leftchild); //先左子树
preorder(r->rightchild); //右
cout << r->data << " "; //根
}
}
void postorder2()
{ //左右根
Stack<stknode<T>> s; //存入栈中的元素,是树节点带左右返回标志
stknode<T> w;
BinTreeNode<T>* p = root;
do
{
while (p != 0)
{
w.ptr = p;
w.tag = 'L';
s.Push(w); //在第一次把根存入,后面存左节点
p = p->leftchild;
}
int continue1 = 1;
while (continue1 && !s.Isempty())
{
s.Pop(w); p = w.ptr;
switch (w.tag)
{
case 'L': w.tag = 'R'; s.Push(w);
continue1 = 0;
p = p->rightchild;
break;
case 'R': cout << p->data; break;
}
}
} while (!s.Isempty());
}
void levelorder(){
SeqQueue< BinTreeNode<T>*> s;
BinTreeNode<T>* p = root;
if(p!=0) s.EnQueue(p);
while (!s.IsEmpty())
{
s.DeQueue(p);
cout << p->data;
if (p->leftchild != 0 )
{
s.EnQueue(p->leftchild);
}
if (p->rightchild != 0)
{
s.EnQueue(p->rightchild);
}
}
cout << endl;
}
bool Isempty() { returun(root == NULL); }
//写一个函数,将左右子树交换,(注意是全部交换)
void exchange(BinTreeNode<T>* r)
{
BinTreeNode<T>* x=r;
if (r != 0)
{
x = r->leftchild;
r->leftchild = r->rightchild;
r->rightchild = x;
exchange(r->leftchild);
exchange(r->rightchild);
}
}
//写一个函数,统计叶子结点总数
void sumnode(BinTreeNode<T>* r,int& i)
{
BinTreeNode<T>* p=r;
if (p != 0)
{
if (p->leftchild == 0 && p->rightchild == 0)
{
i++;
}
}
if(p!=0)
{
sumnode(p->leftchild, i);
sumnode(p->leftchild, i);
}
}
//统计所有结点
int Size(BinTreeNode<T>* r)
{
if (r != 0)
{
return 1+Size(r->leftchild) + Size(r->rightchild);
}
else
{
return 0;
}
}
BinTreeNode<T>* getroot() { return root; }
protected :
BinTreeNode<T>* root;
T Refvalue;
//创建
//广义表的方式 A(B(D,E),Q)#
void CreatBinTree( BinTreeNode<T>*& bt)
{
Refvalue = '#';
Stack<BinTreeNode<char>*> s;
bt = NULL; //把树置空
BinTreeNode<T>* p=bt, * t; int k;
char ch;
cin >> ch;
while (ch != Refvalue)
{
switch (ch)
{
case '(': s.Push(p); k = 1; break; //把左括号进栈,k=1,标志下一次创建左结点
case')': s.Pop(t); break;
case',': k = 2; break; //建立右子树
default:
p = new BinTreeNode<T>(ch);
if (bt == NULL) bt = p; //建立根结点
else if (k == 1) {
s.getTop(t); t->leftchild = p;
}
else
{
s.getTop(t), t->rightchild = p;
}
}
cin >> ch;
}
}
BinTreeNode<T>* Creat(BinTreeNode<T>* bt)
{
char ch;
cin >> ch;
if (ch == '#')
{
bt = 0;
}
else {
bt = new BinTreeNode<T>;
bt->data = ch;
bt->leftchild = Creat(bt->leftchild);
bt->rightchild = Creat(bt->rightchild);
}
return bt;
}
//给输入输出使用的,因为这里是受保护的对象
void destroy(BinTreeNode<T>*& bt)
{
if (bt->leftchild != NULL&&bt->rightchild!=NULL)
{
destroy(bt->leftchild);
destroy(bt->rightchild);
delete bt;
}
};
void Traverse(BinTreeNode<T>* bt, ostream &out) {
if (bt != NULL)
{
out << bt->data << " ";
Traverse(bt->leftchild, out);
Traverse(bt->rightchild, out);
}
}
BinTreeNode<T>* parent(BinTreeNode<T>* subtree, BinTreeNode<T>* current)
{
if (subtree == NULL)
{
return NULL;
}
if (subtree->leftchild == current || subtree->rightchild == current)
{
return subtree;
}
BinTreeNode<T>* p;
if ((p = parent(subtree->leftchild, current)) != NULL) return p;
else return parent(subtree->rightchild, current);
}
friend istream& operator>>(istream& in, BinaryTree<T>& Tree) {
CreatBinTree(in, Tree.root);
return in;
}
friend ostream& operator <<(ostream& out, BinaryTree<T>& Tree) {
out << "前序遍历";
Tree.Traverse(Tree.root, out);
out << endl;
return out;
}
};
作业
//5.24 设具有n个结点的完全二叉树采用顺序存储结构,
//设计算法将该顺序存储结构转换为二叉链式存储结构。
void creatBintree2(T* a, BinTreeNode<T>* &t, int n,int sum)
{
if (n >= sum) return;
if (t == NULL)
{
t = new BinTreeNode<T>(a[n]);
}
creatBintree2(a, t->leftchild, 2 * n + 1,sum);
creatBintree2(a, t->rightchild, 2 * n + 2,sum);
}
template<class T>
//5.29 设具有n个结点的二叉树采用二叉链式存储结构,试写出一个算法将该二叉链式存储结构转换为顺序存储结构。
//这里实现的是完全二叉树,对于普通二叉树是不适用的
//这里对数组初始化,每一个都赋值空格。
//为了实现普通的二叉树,在输出顺序存储结构的数组时,只输出有赋值的元素。
void change_to_LinkBintree(T*& a, BinTreeNode<T>* s, int i, int n)
{
if (i > n)return;
if (s==0)return;
else
{
a[i] = s->data;
}
change_to_LinkBintree(a, s->leftchild, i * 2 + 1, n);
change_to_LinkBintree(a, s->rightchild, i * 2 + 2, n);
}
BinTreeNode<T>* Copy(BinTreeNode<T>* t)
{
BinTreeNode<T>* current;
if (t == 0) return 0;
else
{
current = new BinTreeNode<T>;
current->data = t->data;
current->leftchild = Copy(t->leftchild);
current->rightchild = Copy( t->rightchild);
return current;
}
}