三、树
1.二叉树创建
1.1二叉树先序创建
下面的写法适合给定一个前序排列的字符串,然后据此创建二叉树
class TreeNode
{
public:
char data;
TreeNode *left, *right;
TreeNode() { left = right = NULL; }
};
class BinTree
{
private:
TreeNode *root;
TreeNode *CreateBinTree()
{
char data;
cin >> data;
if (data == '0')
return NULL;
TreeNode *temp = new TreeNode;
temp->data = data;
temp->left = CreateBinTree();
temp->right = CreateBinTree();
return temp;
}
public:
BinTree() { root = CreateBinTree(); }
TreeNode *BTRoot() { return root; }
};
1.2二叉树中后序遍历创建
按中序遍历和后序遍历给出一棵二叉树
#include <iostream>
#include <vector>
using namespace std;
class TreeNode
{
public:
int data;
TreeNode *left, *right;
TreeNode() { left = right = NULL; }
TreeNode(int x) : data(x) { left = right = NULL; }
};
class BinTree
{
public:
TreeNode *root;
int minw;
BinTree() : minw(99999) { root = NULL; }
TreeNode *CreateBinTree(vector<int> ino, vector<int> posto)
{
if (posto.empty())
return NULL;
int rootval = posto[posto.size() - 1];
TreeNode *r = new TreeNode(rootval);
if (posto.size() == 1)
return r;
int cutpos;
for (cutpos = 0; cutpos < ino.size(); cutpos++)
if (ino[cutpos] == rootval)
break;
vector<int> leftino(ino.begin(), ino.begin() + cutpos);
vector<int> rightino(ino.begin() + cutpos + 1, ino.end());
posto.resize(posto.size() - 1);
vector<int> leftposto(posto.begin(), posto.begin() + leftino.size());
vector<int> rightposto(posto.begin() + leftino.size(), posto.end());
r->left = CreateBinTree(leftino, leftposto);
r->right = CreateBinTree(rightino, rightposto);
return r;
}
void PreOrder(TreeNode *r)
{
if (!r)
return;
else if (!r->left && !r->right)
{
if (r->data < minw)
minw = r->data;
return;
}
PreOrder(r->left);
PreOrder(r->right);
}
};
int main(int argc, char const *argv[])
{
int n;
while (cin >> n)
{
vector<int> ino(n), posto(n);
for (int i = 0; i < n; i++)
cin >> ino[i];
for (int i = 0; i < n; i++)
cin >> posto[i];
BinTree bt;
bt.root = bt.CreateBinTree(ino, posto);
bt.PreOrder(bt.root);
cout << bt.minw << endl;
}
return 0;
}
2.二叉树深度
int depth(TreeNode *root) //迭代
{
if (root == NULL)
return 0;
int dep = 0;
queue<TreeNode *> tn;
tn.push(root);
while (!tn.empty())
{
dep++;
int num = tn.size(); //每一层结点的个数
for (int i = 0; i < num; i++)
{
TreeNode *temp = tn.front();
tn.pop();
if (temp->left != NULL)
tn.push(temp->left);
if (temp->right != NULL)
tn.push(temp->right);
}
}
return dep;
}
三行递归
int depth(TreeNode *root)//递归
{
if (root == NULL)
return 0;
return max(depth(root->left), depth(root->right)) + 1;
}
3.二叉排序树创建
二叉排序树(Binary Sort Tree)又称二叉查找树、二叉搜索树。 它或者是一棵空树;或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
class TreeNode
{
public:
int data;
TreeNode *left, *right;
TreeNode() { left = right = NULL; }
};
class BSTree
{
public:
TreeNode *root;
BSTree() { root = NULL; }
void AddintoTree(int num)
{
TreeNode *t = root;
while (true)
{
if (num < t->data)
{
if (t->left == NULL)
{
t->left = new TreeNode;
t->left->data = num;
return;
}
else
{
t = t->left;
}
}
else
{
if (t->right == NULL)
{
t->right = new TreeNode;
t->right->data = num;
return;
}
else
{
t = t->right;
}
}
}
}
};
4.二叉树的遍历1
分别从递归与迭代的角度,研究了二叉树的三种深度优先遍历
递归
void Preorder(TreeNode *root, vector<char> &ans) //递归前序
{
if (root == NULL)
return;
ans.push_back(root->data);
Preorder(root->left, ans);
Preorder(root->right, ans);
}
void Inorder(TreeNode *root, vector<char> &ans) //递归中序
{
if (root == NULL)
return;
Inorder(root->left, ans);
ans.push_back(root->data);
Inorder(root->right, ans);
}
void Postorder(TreeNode *root, vector<char> &ans) //递归后序
{
if (root == NULL)
return;
Postorder(root->left, ans);
Postorder(root->right, ans);
ans.push_back(root->data);
}
迭代
迭代采用的写法是标记法,旨在用NULL空指针去标记栈中未进行处理的结点
vector<char> Preorder(TreeNode *root) //迭代前序
{
vector<char> ans;
stack<TreeNode *> tn;
if (root != NULL)
tn.push(root);
while (!tn.empty())
{
TreeNode *temp = tn.top();
tn.pop();
if (temp != NULL)
{
//前序遍历,入栈顺序是右左根
if (temp->right != NULL)
tn.push(temp->right);
if (temp->left != NULL)
tn.push(temp->left);
tn.push(temp); //放入访问过需要处理的根结点
tn.push(NULL); //放入标记
}
else //遇到NULL表明其后面那个结点是需要处理的
{
temp = tn.top(); //将需要处理的结点取到
tn.pop(); //弹出
ans.push_back(temp->data); //处理结点
}
}
return ans;
}
vector<char> Inorder(TreeNode *root) //迭代中序
{
vector<char> ans;
stack<TreeNode *> tn;
if (root != NULL)
tn.push(root);
while (!tn.empty())
{
TreeNode *temp = tn.top();
tn.pop();
if (temp != NULL)
{
//中序遍历,入栈顺序是右根左
if (temp->right != NULL)
tn.push(temp->right);
tn.push(temp); //放入访问过需要处理的根结点
tn.push(NULL); //放入标记
if (temp->left != NULL)
tn.push(temp->left);
}
else //遇到NULL表明其后面那个结点是需要处理的
{
temp = tn.top(); //将需要处理的结点取到
tn.pop(); //弹出
ans.push_back(temp->data); //处理结点
}
}
return ans;
}
vector<char> Postorder(TreeNode *root) //迭代后序null标记需要处理的结点
{
vector<char> ans;
stack<TreeNode *> tn;
if (root != NULL)
tn.push(root);
while (!tn.empty())
{
TreeNode *temp = tn.top();
tn.pop();
if (temp != NULL)
{
//后序遍历,入栈顺序是根右左
tn.push(temp); //放入访问过需要处理的根结点
tn.push(NULL); //放入标记
if (temp->right != NULL)
tn.push(temp->right);
if (temp->left != NULL)
tn.push(temp->left);
}
else //遇到NULL表明其后面那个结点是需要处理的
{
temp = tn.top(); //将需要处理的结点取到
tn.pop(); //弹出
ans.push_back(temp->data); //处理结点
}
}
return ans;
}
5.二叉树的广度优先遍历
二叉树广度优先遍历,层次遍历
vector<char> Levelorder(TreeNode *root) //层次遍历
{
vector<char> ans;
queue<TreeNode *> tn;
if (root != NULL)
tn.push(root);
while (!tn.empty())
{
int size = tn.size();
for (int i = 0; i < size; i++)
{
TreeNode *temp = tn.front();
tn.pop();
ans.push_back(temp->data);//处理
if (temp->left != NULL)
tn.push(temp->left);
if (temp->right != NULL)
tn.push(temp->right);
}
}
return ans;
}