二叉链表1
思路
当写构造函数时,是先new一个新的BiNode类型,再利用递归来创造左右子树
而析构函数中,是先递归左右子树,再将自身叶子析构(删除)。
实现
//OJ-1020 binary tree(1)
#include <iostream>
#include <string>
using namespace std;
//二叉树类,实现二叉树的递归算法:三种遍历
template <typename DataType>
struct BiNode //二叉树的结点结构
{
DataType data;
BiNode<DataType>* lchild, * rchild;
};
template <typename DataType>
class BiTree {
public:
BiTree(); //构造函数,初始化一棵二叉树,其前序序列由键盘输入
~BiTree(); //析构函数,释放二叉链表中各结点的存储空间
void PreOrder(void); //调用私有的递归函数PerOrder
void InOrder(void);
void PostOrder(void);
private:
BiNode<DataType>* root; //指向根结点的头指针
void Creat(BiNode<DataType>*& bt);//被构造函数调用,递归方式生成二叉树
void Release(BiNode<DataType>*& bt); //被析构函数调用
void PreOrder(BiNode<DataType>* bt); //前序遍历二叉树
void InOrder(BiNode<DataType>* bt); //中序遍历二叉树
void PostOrder(BiNode<DataType>* bt); //后序遍历二叉树
};
//定义类中的成员函数
//构造函数:Creat利用创建二叉树
template<typename DataType>
BiTree<DataType>::BiTree()
{
Creat(root);
}
//功 能:递归方法创建一棵二叉树,由构造函数调用
template <typename DataType>
void BiTree<DataType>::Creat(BiNode<DataType>*& bt)
{
DataType ch;
cin >> ch;
if (ch == "#") bt = nullptr; //创建结点值为字符串的二叉树,遇到#则不再创建
else {
bt = new BiNode<DataType>; //生成一个结点
bt->data = ch;
Creat(bt->lchild); //递归建立左子树
Creat(bt->rchild); //递归建立右子树
}
}
//功 能:析构函数,释放二叉链表中各结点的存储空间
template<typename DataType>
BiTree<DataType>::~BiTree() //析构函数不能带参数
{
Release(root);
}
//功 能:释放二叉树的存储空间,析构函数调用
template<typename DataType>
void BiTree<DataType>::Release(BiNode<DataType>*& bt)
{
if (bt != nullptr) {//从上往下释放,不为空就释放
Release(bt->lchild); //释放左子树
Release(bt->rchild); //释放右子树
delete bt;
}
}
template<typename DataType>
void BiTree<DataType>::PreOrder(void)
{
PreOrder(root);
}
template<typename DataType>
void BiTree<DataType>::InOrder(void)
{
InOrder(root);
}
template<typename DataType>
void BiTree<DataType>::PostOrder(void)
{
PostOrder(root);
}
//请在下面补充实现二叉树的三种递归遍历算法
template<typename DataType>
void BiTree<DataType>::PreOrder(BiNode<DataType>* bt)
{
if (bt==NULL)return;
cout << bt->data << " ";
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
template<typename DataType>
void BiTree<DataType>::InOrder(BiNode<DataType>* bt)
{
if (bt == NULL)return;
InOrder(bt->lchild);
cout << bt->data << " ";
InOrder(bt->rchild);
}
template<typename DataType>
void BiTree<DataType>::PostOrder(BiNode<DataType>* bt)
{
if (bt == NULL)return;
PostOrder(bt->lchild);
PostOrder(bt->rchild);
cout << bt->data << " ";
}
int main()
{
BiTree<string> mybit;
mybit.PreOrder();
cout << endl;
mybit.InOrder();
cout << endl;
mybit.PostOrder();
cout << endl;
return 0;
}
二叉链表2
思路
求叶子数
1.特殊情况:本元素不存在,空树,返回0
2.情况1:左子树右子树均不存在
但此元素存在,故返回1
3.用count从顶端递归左右子树加和
4.return count
求深度
1.特殊情况:本元素不存在,空树,返回0
2.用递归计算最顶端的左子树,右子树的深度
3.返回两个值中最大的值+1(顶端的叶子)
实现
#include <iostream>
#include <string>
/*递归算法计算二叉树的叶子个数和高度。请完成如三个算法:
int CountLeaf(BiNode<T> *); //递归算法计算叶子数
int Depth(BiNode<T> *); //递归算法计算高度
BiNode<DataType> *GetRoot(); //获取私有量root的值
部分已知代码如下,请在此基础上补充完善代码:
*/
//二叉树类,实现计算高度、叶子数
//OJ-1021 binary tree(2)
#include <iostream>
#include <string>
using namespace std;
template <typename DataType>
struct BiNode //二叉树的结点结构
{
DataType data;
BiNode<DataType>* lchild, * rchild;
};
template <typename DataType>
class BiTree {
public:
BiTree(); //构造函数,初始化一棵二叉树,其前序序列由键盘输入
~BiTree(); //析构函数,释放二叉链表中各结点的存储空间
int CountLeaf(BiNode<DataType>*); //递归方法计算叶子数
int Depth(BiNode<DataType>*); //递归方法计算高度
BiNode<DataType>* GetRoot(); //获取私有量root的值
int CountLeaf(); //调用上面的递归算法计算叶子
int Depth(); //调用上面的递归算法计算高度
private:
BiNode<DataType>* root; //指向根结点的头指针
void Creat(BiNode<DataType>*& bt);//被构造函数调用,递归方式生成二叉树
void Release(BiNode<DataType>*& bt); //被析构函数调用
};
//定义类中的成员函数
//构造函数:Creat利用创建二叉树
template<typename DataType>
BiTree<DataType>::BiTree()
{
Creat(root);
}
//功 能:递归方法创建一棵二叉树,由构造函数调用
template <typename DataType>
void BiTree<DataType>::Creat(BiNode<DataType>*& bt)
{
DataType ch;
cin >> ch;
if (ch == "#") bt = nullptr; //创建结点值为字符串的二叉树
else
{
bt = new BiNode<DataType>; //生成一个结点
bt->data = ch;
Creat(bt->lchild); //递归建立左子树
Creat(bt->rchild); //递归建立右子树
}
}
//功 能:析构函数,释放二叉链表中各结点的存储空间
template<typename DataType>
BiTree<DataType>::~BiTree() //析构函数不能带参数
{
Release(root);
}
//功 能:释放二叉树的存储空间,析构函数调用
template<typename DataType>
void BiTree<DataType>::Release(BiNode<DataType>*& bt)
{
if (bt != nullptr) {
Release(bt->lchild); //释放左子树
Release(bt->rchild); //释放右子树
delete bt;
}
}
template <typename DataType>
int BiTree<DataType>::Depth()
{
return Depth(root);
}
template <typename DataType>
int BiTree<DataType>::CountLeaf()
{
return CountLeaf(root);
}
//请在下面补充相关算法的实现
template <typename DataType>
int BiTree<DataType>::CountLeaf(BiNode<DataType>* bt)
{
if (bt == NULL)return 0;
if (bt->lchild == NULL && bt->rchild == NULL)
{
return 1;
}
int count = 0;
count = CountLeaf(bt->lchild) + CountLeaf(bt->rchild);
return count;
//本元素不存在 左右子树均不存在 用count递归,加和 返回
}
template <typename DataType>
int BiTree<DataType>::Depth(BiNode<DataType>* bt)
{
if (bt == NULL)return 0;//如果此元素不存在,直接return 0
int ldepth = Depth(bt->lchild);
int rdepth = Depth(bt->rchild);
return max(ldepth, rdepth) + 1;//+1的作用是包含本元素
//本元素不存在 左右分别递归 最大值+1
}
template <typename DataType>
BiNode<DataType>* BiTree<DataType>::GetRoot()
{
return root;
}
int main()
{
BiTree<string> mybit;
cout << mybit.CountLeaf() << " " << mybit.Depth() << endl;
BiNode<string>* broot;
broot = mybit.GetRoot();
cout << mybit.CountLeaf(broot) << " " << mybit.Depth(broot) << endl;
return 0;
}
二叉链表3
思路
层次遍历算法(队列)
初始化Q[],q,front,rear
特殊情况:root为空,树空,直接return
入列
循环(只要队列不为空就一直循环)
{
出列
输出
如果左不为空,左子树入列
如果右不为空,右子树入列
}
先序遍历算法(栈)
初始化 一个二叉树指针数组Q,一个二叉树指针q指向根,top=-1
循环(q为空和栈为空才停止循环)
{
while(q不为空则一直循环)
{
输出
入栈
访问左子树
}
如果栈非空
{
出栈
访问右子树
}
}
实现
#include<iostream>
#include<string>
using namespace std;
//循环队列类
const int QueueSize = 50; //定义存储队列元素的数组的最大长度
template <class DataType> //定义模板类CirQueue
class Queue
{
public:
Queue(); //构造函数,置空队
~Queue(); //析构函数
void EnQueue(DataType x); //将元素x入队
DataType DeQueue(); //将队头元素出队
DataType GetQueue(); //取队头元素(并不删除)
bool Full(); //judge full
bool Empty(); //判断队列是否为空
private:
DataType data[QueueSize]; //存放队列元素的数组
int front; //队头指针,指向队头元素的前一个位置
int rear; //队尾指针,指向队尾元素的位置
};
/*
* 前置条件:队列不存在
* 输 入:无
* 功 能:初始化队列
* 输 出:无
* 后置条件:创建一个空队列
*/
template <typename DataType>
Queue<DataType>::Queue()
{
front = rear = QueueSize - 1;
}
/*
* 前置条件:队列已存在
* 输 入:无
* 功 能:销毁队列
* 输 出:无
* 后置条件:释放队列所占用的存储空间
*/
template <typename DataType>
Queue<DataType>::~Queue()
{
}
/*
* 前置条件:队列已存在
* 输 入:元素值x
* 功 能:在队尾插入一个元素
* 输 出:如果插入不成功,抛出异常
* 后置条件:如果插入成功,队尾增加了一个元素
*/
template <typename DataType>
void Queue<DataType>::EnQueue(DataType x)
{
if (Full()) throw "上溢";
rear = (rear + 1) % QueueSize; //队尾指针在循环意义下加1
data[rear] = x; //在队尾处插入元素
}
/*
* 前置条件:队列已存在
* 输 入:无
* 功 能:删除队头元素
* 输 出:如果删除成功,返回被删元素值,否则,抛出删除异常
* 后置条件:如果删除成功,队头减少了一个元素
*/
template <typename DataType>
DataType Queue<DataType>::DeQueue()
{
if (Empty()) throw "下溢";
front = (front + 1) % QueueSize; //队头指针在循环意义下加1
return data[front]; //读取并返回出队前的队头元素,注意队头指针
}
//指向队头元素的前一个位置
/*
* 前置条件:队列已存在
* 输 入:无
* 功 能:读取队头元素
* 输 出:若队列不空,返回队头元素
* 后置条件:队列不变
*/
template <typename DataType>
DataType Queue<DataType>::GetQueue()
{
int i;
if (Empty()) throw "下溢";
i = (front + 1) % QueueSize; //注意不要给队头指针赋值
return data[i];
}
/*
* 前置条件:队列已存在
* 输 入:无
* 功 能:判断队列是否为空
* 输 出:如果队列为空,返回true,否则,返回false
* 后置条件:队列不变
*/
template <typename DataType>
bool Queue<DataType>::Empty()
{
return front == rear;
}
template <typename DataType>
bool Queue<DataType>::Full()
{
return (rear + 1) % QueueSize == front;
}
//栈类
const int StackSize = 50;
template <typename DataType>
class Stack {
public:
Stack(); //initialize an empty stack
void Push(DataType x);
DataType Pop();
bool Full(); //return true if full
bool Empty(); //return true if empty
private:
DataType data[StackSize];
int top; //subscript of array
};
//initialize an empty stack
template <typename DataType>
Stack<DataType>::Stack()
{
top = -1;
}
//push x
template <typename DataType>
void Stack<DataType>::Push(DataType x)
{
if (Full())throw"Overflow";
data[++top] = x;
}
//pop the top element of stack
template <typename DataType>
DataType Stack<DataType>::Pop()
{
if (Empty())throw "Empty";
DataType x;
x = data[top--];
return x;
}
//judge empty
template <typename DataType>
bool Stack<DataType>::Full()
{
return top == StackSize - 1;
}
//judge empty
template <typename DataType>
bool Stack<DataType>::Empty()
{
return top == -1;
/* if(top==-1)return true;
else return false;*/
}
//二叉树类,实现二叉树的非递归算法:先序遍历、层次遍历
template <typename DataType>
struct BiNode //二叉树的结点结构
{
DataType data;
BiNode<DataType>* lchild, * rchild;
};
template <typename DataType>
class BiTree {
public:
BiTree(); //构造函数,初始化一棵二叉树,其前序序列由键盘输入
~BiTree(); //析构函数,释放二叉链表中各结点的存储空间
void PreOrder(void); //先序非递归
void LevelOrder(void); //层次遍历
private:
BiNode<DataType>* root; //指向根结点的头指针
void Creat(BiNode<DataType>*& bt);//被构造函数调用,递归方式生成二叉树
void Release(BiNode<DataType>*& bt); //被析构函数调用
};
//定义类中的成员函数
//构造函数:Creat利用创建二叉树
template<typename DataType>
BiTree<DataType>::BiTree()
{
Creat(root);
}
//功 能:递归方法创建一棵二叉树,由构造函数调用
template <typename DataType>
void BiTree<DataType>::Creat(BiNode<DataType>*& bt)
{
DataType ch;
cin >> ch;
if (ch == "#") bt = nullptr; //创建结点值为字符串的二叉树
else {
bt = new BiNode<DataType>; //生成一个结点
bt->data = ch;
Creat(bt->lchild); //递归建立左子树
Creat(bt->rchild); //递归建立右子树
}
}
//功 能:析构函数,释放二叉链表中各结点的存储空间
template<typename DataType>
BiTree<DataType>::~BiTree() //析构函数不能带参数
{
Release(root);
}
//功 能:释放二叉树的存储空间,析构函数调用
template<typename DataType>
void BiTree<DataType>::Release(BiNode<DataType>*& bt)
{
if (bt != nullptr) {
Release(bt->lchild); //释放左子树
Release(bt->rchild); //释放右子树
delete bt;
}
}
//请在下面补充实现先序、层次遍历算法
template <typename DataType>
void BiTree<DataType>::LevelOrder(void)
{
BiNode<DataType>* Q[100], *q = NULL;
int front = -1, rear = -1;
if (root == NULL)return;
Q[++rear] = root;
while (rear != front)
{
q = Q[++front];
cout << q->data<<" " ;
if (q->lchild != NULL)Q[++rear] = q->lchild;
if (q->rchild != NULL)Q[++rear] = q->rchild;
}
//初始化Q,q,front,rear 本元素不存在 入列 循环
//出列,输出,条件入列
}
template <typename DataType>
void BiTree<DataType>::PreOrder(void)
{
//q=NULL是指当前访问内容为空
//top=-1是栈里没东西了
BiNode<DataType>* Q[100], * q=root;
int top = -1;
while (q != NULL || top != -1)//两个条件都不成立才退出循环
{
while (q != NULL)
{
cout << q->data << " ";//输出当前元素值
Q[++top] = q;//s入栈
q = q->lchild;//访问左子树
}
if (top != -1)//栈非空
{
q = Q[top--];//出栈
q = q->rchild;//访问右子树
}
//输出 入栈 左子树 出栈 右子树
}
}
int main()
{
BiTree<string> bt;
bt.PreOrder();
cout << endl;
bt.LevelOrder();
cout << endl;
return 0;
}
顺序存储二叉树
题目描述
顺序存储的二叉树,依次实现二叉树的三种递归遍历:先序、中序、后序;二叉树的先序非递归、层次遍历;计算二叉树的叶子个数、高度。部分代码已知,请勿改动,将其它代码补充完整,达到相应的输出结果。
输入
ABD#C####EF############
输出
A B C E F D
B E C F A D
E F C B D A
A B C E F D
A B D C E F
3 4
代码示例
#include<bits/stdc++.h>
using namespace std;
//循环队列类
const int QueueSize = 100; //循环队列的最大长度
template <class T> //定义模板类CirQueue
class CirQueue
{
public:
CirQueue(); //构造函数,置空队
~CirQueue(); //析构函数
void EnQueue(T x); //将元素x入队
T DeQueue(); //将队头元素出队
T GetQueue(); //取队头元素(并不删除)
bool Empty(); //判断队列是否为空
bool Full();
private:
T data[QueueSize]; //存放队列元素的数组
int front, rear; //队头和队尾指针,分别指向队头元素的前一个位置和队尾元素的位置
};
//功 能:初始化空队列
template <class T>
CirQueue<T>::CirQueue()
{
front = rear = 0;
}
// 功 能:销毁队列
template <class T>
CirQueue<T>::~CirQueue()
{
}
//功 能:元素x入队
template <class T>
void CirQueue<T>::EnQueue(T x)
{
if (Full()) throw "Overflow";
rear = (rear + 1) % QueueSize; //队尾指针在循环意义下加1
data[rear] = x; //在队尾处插入元素
}
//功 能:队头元素出队,返回值为出队元素
template <class T>
T CirQueue<T>::DeQueue()
{
if (Empty()) throw "Downflow";
front = (front + 1) % QueueSize; //队头指针在循环意义下加1
return data[front]; //读取并返回出队前的队头元素,注意队头指针
}
//指向队头元素的前一个位置
// 功 能:获取队头元素
template <class T>
T CirQueue<T>::GetQueue()
{
int i;
if (Empty()) throw "Downflow";
i = (front + 1) % QueueSize; //注意不要给队头指针赋值
return data[i];
}
// 功 能:判断队列是否为空,若空返回true,否则返回false
template <class T>
bool CirQueue<T>::Empty()
{
return front == rear;
}
//功 能:判断队列是否满,若满返回true,否则false
template <class T>
bool CirQueue<T>::Full()
{
return (rear + 1) % QueueSize == front;
}
//栈类
const int StackSize = 100; //10只是示例性的数据,可以根据实际问题具体定义
template <class T> //定义模板类SeqStack
class SeqStack
{
public:
SeqStack(); //构造函数,栈的初始化
~SeqStack(); //析构函数
void Push(T x); //将元素x入栈
T Pop(); //将栈顶元素弹出
T GetTop(); //取栈顶元素(并不删除)
bool Empty(); //判断栈是否为空
bool Full(); //判断栈是否为满
private:
T data[StackSize]; //存放栈元素的数组
int top; //栈顶指针,指示栈顶元素在数组中的下标
};
//初始化空栈
template <class T>
SeqStack<T>::SeqStack()
{
top = -1;
}
//功 能:销毁栈
template <class T>
SeqStack<T>::~SeqStack()
{
}
//功 能:元素x压栈
template <class T>
void SeqStack<T>::Push(T x)
{
if (Full()) throw "Overflow";
top++;
data[top] = x;
}
// 功 能:栈顶元素弹栈
template <class T>
T SeqStack<T>::Pop()
{
T x;
if (Empty()) throw "Downflow";
x = data[top--];
return x;
}
// 功 能:读取当前的栈顶元素
template <class T>
T SeqStack<T>::GetTop()
{
if (Empty())throw"Downflow";
return data[top];
}
//功 能:判断栈是否为空
template <class T>
bool SeqStack<T>::Empty()
{
if (top == -1) return 1;
else return 0;
}
//功 能:判断栈是否为满
template <class T>
bool SeqStack<T>::Full()
{
return top == StackSize - 1;
}
//顺序二叉树类
const int TreeSize = 100; //最大长度
template <class T>
class BiTree {
public:
BiTree(T*); //构造函数,初始化一棵二叉树,其前序序列由键盘输入
void PreOrder(int pos); //前序遍历二叉树
void InOrder(int pos); //中序遍历二叉树
void PostOrder(int pos); //后序遍历二叉树
int CountLeaf(int pos); //计算叶子结点总数
int Depth(int pos); //计算高度
void PreOrder(); //非递归先序遍历
void LevelOrder(); //层次遍历
private:
T data[TreeSize];
//存储结点的元素值,根结点存储在1下标,双亲下标为i,则左右孩子依次为2i,2i+1
};
//constructor
template <class T>
BiTree<T>::BiTree(T* str)
{
strcpy(data + 1, str);
}
template <class T>
void BiTree<T>::PreOrder(int pos)
{
if (data[pos] == '#')return;
cout << data[pos]<<" ";
PreOrder(pos * 2);
PreOrder(pos * 2 + 1);
}
template <class T>
void BiTree<T>::InOrder(int pos)
{
if (data[pos] == '#')return;
InOrder(pos * 2);
cout << data[pos]<<" ";
InOrder(pos * 2 + 1);
}
template <class T>
void BiTree<T>::PostOrder(int pos)
{
if (data[pos] == '#')return;
PostOrder(pos * 2);
PostOrder(pos * 2 + 1);
cout << data[pos]<<" ";
}
template <class T>
int BiTree<T>::CountLeaf(int pos)
{
if (data[pos] == '#')return 0;
else if (data[pos * 2] == '#' && data[pos * 2 + 1] == '#')return 1;
else return CountLeaf(pos * 2) + CountLeaf(pos * 2 + 1);
}
template <class T>
int BiTree<T>::Depth(int pos)
{
if (data[pos] == '#')return 0;
return max(Depth(pos * 2), Depth(pos * 2 + 1))+1;
}
template <class T>
void BiTree<T>::PreOrder()
{
int pos = 1;
stack<T> s;
while (!s.empty()||data[pos]!='#')
{
while (data[pos] != '#')//左
{
cout << data[pos] << " ";
s.push(pos);
pos <<= 1;
}
if (!s.empty()) {//右
pos = s.top();
s.pop();
pos = pos * 2 + 1;
}
}
}
template <class T>
void BiTree<T>::LevelOrder()
{
int pos = 1;
if (data[pos] == '#')return ;
queue<T> q;
q.push(pos);
while (!q.empty())
{
int t = q.front();
q.pop();
cout << data[t]<<" ";
if (data[t * 2] != '#')q.push(t * 2);
if (data[t * 2+1 ] != '#')q.push(t * 2+1);
}
}
int main()
{
char str[80];
cin >> str;
BiTree<char> bt(str);
bt.PreOrder(1);
cout << endl;
bt.InOrder(1);
cout << endl;
bt.PostOrder(1);
cout << endl;
bt.PreOrder();
cout << endl;
bt.LevelOrder();
cout << endl;
cout << bt.CountLeaf(1) << " " << bt.Depth(1) << endl;
return 0;
}