二叉树
//完全二叉树,满二叉树
//完全二叉树:有N层结点的二叉树,其中N-1层为满二叉树,且第N层的叶子结点从左向右,要么只有左叶子结点,不会存在只有右叶子节点没有左叶子节点的情况
//二叉树的存储有顺式存储即数组,也有链式存储即链表
//二叉树的基本操作即遍历
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
typedef struct Node
{
char *data;
Node* lchild;
Node* rchild;
struct Node* next;
};
**先序遍历 VLR**
//判断根结点是否存在,若存在则入栈列,
//判断栈顶元素是否为空,若不为空则访问,出栈,
//栈顶元素的左右孩子不为空则入栈
void priorSearch(Node* head)
{
stack<Node*>s;
if (head == NULL)
return;
Node* cur = head;
while (!s.empty()||cur) //当很结点和栈步同时为空说明遍历没有结束
{
while(cur) //先序遍历遇到根结点则直接入栈
{
cout << cur->data;
s.push(cur);
cur = cur->lchild;
}
Node* top = s.top(); //取栈顶元素说明根结点已经左子树已经访问过了
s.pop();
cur = top->rchild; //以子问题的方式访问右子树
}
}
**中序遍历 LVR**
void middleSearch(Node* head)
{
stack<Node*>s;
Node* cur = head;
while (!s.empty() || cur) //当根结点和栈步同时为空说明没有遍历完成
{
while (cur) //中序遍历遇到根节点直接入栈
{
s.push(cur);
cur = cur->lchild;
}
Node* top = s.top(); //取栈顶元素,说明左子树和根节点已经访问过了
cout << top->data; //访问栈顶元素(即根结点)
s.pop();
top = top->rchild; //以子问题的方式访问右子树
}
}
**后序遍历 LRV**
void laterSearch(Node* head)
{
stack<Node*>s;
Node*cur = head;
Node* pre = NULL;
while (!s.empty() || cur) //当根节点和栈不同时为空说明遍历没有结束
{
while (cur)//遇到根结点入栈
{
s.push(cur);
cur = cur->lchild;
}
Node* top = s.top(); //栈顶元素不一点可以访问
if (top->lchild == NULL || top->rchild == pre) //若栈顶元素左结点为空或右节点已经访问过才可以进行访问
{
cout << top->data; //访问栈顶元素 (即根结点)
top = pre;//更新前一个结点
s.pop();
}
else
{
cur = cur->rchild; //以子问题的方式访问右子树
}
}
}
**层序遍历 **
void levelSearch(Node* head)
{
queue<Node*>q;
if (head)
q.push(head); //根结点入队列
while (!q.empty())
{
Node* front = q.front();
cout << front->data;
q.pop();
if (front->lchild != NULL)
q.push(front->lchild);
if (front->rchild != NULL)
q.push(front->rchild);
}
}
建造二叉树
//二叉树的构造
#include<iostream>
#include<cassert>
#include<queue>
#include<stack>
using namespace std;
template<class T>
struct TreeNode
{
TreeNode(const T&val = T())
:_val(val)
, _lchild(0)
, _rchild(0)
{}
T _val; //节点值
TreeNode<T>* _lchild; //左孩子,右孩子
TreeNode<T>* _rchild;
};
template<class T>
class BinaryTree
{
public:
typedef Node<T> node;
BinaryTree() //无参构造函数
:_root(NULL)
{}
BinaryTree(const T*a, size_t size, const T& val) //带参构造函数
{
assert(a);
size_t index = 0;
_root = CreatTree(a, size, val, index);
}
BinaryTree(const BinaryTree<T>& b) //拷贝构造
{
_root = Copy(b._root);
}
BinaryTree& operator=(const BinaryTree<T>& b) //赋值运算符重载
{
//if (this != &b)
//{
// Node* tmp = Copy(b._root);
// Destroy(_root);
// _root = tmp;
//}
swap(b._root, _root);
return *this;
}
~BinaryTree() //析构函数
{
if (NULL != _root)
{
Destroy(_root);
_root = NULL;
}
}
protected: //按照先序遍历递归建树
Node* CreateTree(const T* a, size_t size, const T&val, size_t &index)
{
assert(a);
Node* root == NULL;
if (a[index]!=val&&index<size)
{
root = new Node(a[index]);
root->lchild = CreateTree(a, size, val, ++index);
root->rchild = CreateTree(a, size, val, ++index);
}
return root;
}
Node* Copy(Node* root) //拷贝对象
{
Node* tmp = NULL;
if (root)
{
tmp = new Node(root->val);
tmp->lchild = Copy(root->_lchild);
tmp->rchild = Copy(root->_rchild);
}
return tmp;
}
void Destroy(Node* &root) //释放空间
{
if (root) //用后序遍历方式释放空间
{
Destroy(root->_lchild);
Destroy(root->_rchild);
delete root;
root = NULL;
}
}
private:
Node* _root; //根节点
};
常见二叉树问题
//求树的深度
size_t Depth(Node* root)
{
if (root == NULL)
return 0;
else
return Depth(root->lchild) > Depth(root->rchild) ?
(Depth(root->lchild) + 1) : (Depth(root->rchild) + 1);
}
//求二叉树中节点个数
size_t Size(Node* root)
{
size_t count = 0;
if (root == NULL)
{
count = 0;
}
else
{
//节点个数=左子树节点+右子树节点+1
count = Size(root->lchild) + Size(root->rchild) + 1;
}
return count;
}
//求二叉树中叶子节点的个数
size_t leafsize(Node* root)
{
if (root == NULL)
return 0;
if (root->lchild == NULL&&root->rchild == NULL)
{
return 1;
}
else
{
return leafsize(root->lchild) + leafsize(root->rchild);
}
}
//求二叉树第K层的节点个数
size_t Klevelsize(Node* root, size_t k)
{
size_t count = 0;
if (root == NULL)
return 0;
if (k == 1)
{
count++;
}
else
{
count = Klevelsize(root->lchild, k - 1) + Klevelsize(root->rchild, k - 1);
}
return count;
}
//判断一棵树是否为完全二叉树
bool IsComplete(Node* root)
{
bool flag = true;
queue<Node*>q;
q.push(root);
while (!q.empty()) //运用队列进行层序遍历
{
Node* front = q.front();
q.pop(); //如果队首元素的左子树为空,则标志位假,如果层序遍历后面的节点还有子树说明不是完全二叉树
if (front->lchild == NULL)
flag = false;
else
{
if (flag == false)
{
return false;
}
q.push(front->lchild);
}
if (front->rchild == NULL)
flag = false;
else
{
if (flag == false)
return false;
q.push(front->rchild);
}
}
return true;
}
//二叉树的镜像
void MirrorTree(Node* root)
{
if (root == NULL)
return;
swap(root->lchild, root->rchild);
MirrorTree(root->lchild);
MirrorTree(root->rchild);
}