一、 树
- 树是具有层次结构的n(n>0)个结点的有限集。
![]()
树的结点包含一个数据元素及若干指向其子树的分支。
结点的度:结点拥有子树的数量;A的度为3,K的度为0。
叶子结点(终端结点):度为0的结点;K、L、F、G、M、I、J为叶子结点。
分支结点(非终端结点):度不为0的结点。A、B、C、D、E、H为分支结点。
内部结点:除根结点外,其余分支结点;B、C、D、E、H为内部结点。
有序树:有序树的子树从左到右是有序的;
例如:B是A的第1个孩子;D是A的最后一个孩子。
森林:m(m>0)棵互不相交的树;
二、 二叉树
二叉树的每个结点至多有两棵子树,且二叉树的子树有左右之分,次序不能颠倒。(二叉树是一个递归定义)。
二叉树的存储方式:
2.1 顺序存储结构:用一组地址连续的存储单元依次自上而下、自左而右存储二叉树上的结点元素。仅适用于完全二叉树(完全二叉树包含满二叉树)。
2.2 链式存储结构:
2.2.1: (二叉链表)链表结点包含3个域:数据域、左指针域、右指针域
2.2.2: (三叉链表)链表结点包含4个域:数据域、左指针域、父指针域、右指针域
三、 遍历二叉树
遍历二叉树:按照某条搜索路径访问树中的每个结点,使得每个结点均被访问一次,且仅被访问一次。
二叉树遍历实现了对一个非线性结构进行线性化的操作,从而使每个结点在线性序列中有且只有一个直接前驱和直接后继。
按照根节点被访问的顺序,有3种遍历方案:先序遍历、中序遍历、后序遍历;二叉树的遍历方案也是递归。
二叉树的递归遍历:先序遍历,中序遍历,后序遍历;以及非递归遍历:先序遍历,中序遍历;层次遍历代码如下:
#include "stdafx.h"
#include "iostream"
#include "stack"
#include "queue"
using namespace std;
typedef char ElemType;
typedef struct node
{
ElemType data;
struct node *lChild, *rChild;
}BiTNode,*BiTree;
//按照先序顺序创建二叉树
void createBiTree(BiTree &T) {
ElemType elem;
//'#'代表空树
cin >> elem;
if (elem=='#') //递归的出口条件
{
T = NULL;
}
else
{
T = new node;
T->data = elem;
createBiTree(T->lChild);
createBiTree(T->rChild);
}
}
void visit(ElemType elem) {
if (elem!='#')
cout << elem << " ";
}
//递归写法,先序遍历
void preOrderTraverse(BiTree &T) {
if (T!=NULL) {
visit(T->data);
preOrderTraverse(T->lChild);
preOrderTraverse(T->rChild);
}
}
//中序遍历
void inOrderTraverse(BiTree &T) {
if (T!=NULL)
{
inOrderTraverse(T->lChild);
visit(T->data);
inOrderTraverse(T->rChild);
}
}
//后序遍历
void postOrderTraverse(BiTree &T) {
if (T!=NULL)
{
postOrderTraverse(T->lChild);
postOrderTraverse(T->rChild);
visit(T->data);
}
}
//非递归遍历,将T入栈,遍历完左子树返回时,栈顶应该为T,T出栈,然后访问右子树
void postOrderTraverse2(BiTree &T) {
stack<BiTree> stack;
if (T==NULL)
{
cout << "二叉树不存在!" << endl;
exit(1);
}
BiTree p = T;
//栈或当前结点p不为空时循环
while(p||!stack.empty())
{
if (p!=NULL)
{
stack.push(p);
visit(p->data);
p = p->lChild;
}
else
{
p = stack.top();
stack.pop();
p = p->rChild;
}
}
}
//非递归遍历,中序遍历
void inOrderTraverse2(BiTree &T) {
stack<BiTree> stack;
BiTree p = T;
while (p||!stack.empty())
{
if (p!=NULL)
{
stack.push(p);
p = p->lChild;
}
else
{
p = stack.top();
visit(p->data);
stack.pop();
p = p->rChild;
}
}
}
//按层次遍历,运用队列,自顶向下,自左向右逐层访问每个结点
void levelOrderTraverse(BiTree &T) {
BiTree p = T;
queue<BiTree> queue;
queue.push(p); //根结点入队
while (!queue.empty())
{
p = queue.front(); //遍历队头节点,出队,
visit(p->data);
queue.pop();
if (p->lChild!=NULL) //每次都将队头节点的左、右子结点入队
{
queue.push(p->lChild);
}
if (p->rChild!=NULL)
{
queue.push(p->rChild);
}
}
}
int main()
{
BiTree tree;
createBiTree(tree);
cout << "递归遍历:"<<endl;
cout << "先序遍历:";
preOrderTraverse(tree);
cout << endl << "中序遍历:";
inOrderTraverse(tree);
cout << endl << "后序遍历:";
postOrderTraverse(tree);
cout << endl << "非递归遍历" << endl;
cout << "先序遍历:";
postOrderTraverse2(tree);
cout << endl << "中序遍历:";
inOrderTraverse2(tree);
cout << endl;
cout << "层次遍历:";
levelOrderTraverse(tree);
cout << endl;
return 0;
}