ディレクトリ
ツリーの基本的な操作
バイナリツリーノード構造定義
typedef struct btnode *btlink //定义一个指向数据类型为btnode的指针
typedef struct btnode
{
TreeItem element;
btlink *lchild;
btlink *rchild;
}Btnode;
新しいツリーノードを作成します。
btlink NewBNode() //返回值是一个指针,即新结点的地址值
{
btlink p;
p=malloc(sizeof(Btnode));
if(p) //申请地址成功
return p;
else
Error("Exhausted memory.");
}
二分木構造の定義
typedef struct binarytree *BinaryTree;
typedef struct binarytree
{
btlink root; //root是指向树根的指针,一个二叉树只要知道其树根便可唯一确定
}BTree;
空のバイナリツリーを作成します
BinaryTree BinaryInit()
{
BinaryTree T=malloc(sizeof(*T));
T->root=0; //初始化指针,未指向任何空间
return T;
}
ルートBinaryEmpty(T)Tは、ルートポインタが空で検出され
int BinaryEmpty(BinaryTree T) //这里的T是指针,指向一个二叉树的根结点
{
return(T->root==0)
}
ルートノード番号を返すようにルート(T)
TreeItem Root(BinaryTree T)
{
if(BinaryEmpty(T))
{
Error("Tree is empty.");
}
else return T->root->element;
}
MakeTree(X、T、L、R)xには、それぞれ、左および右の部分木構築新しいバイナリツリーT.ためのLとRのルート要素であります
void MakeTree(TreeItem x,BinaryTree T,BinaryTree L,BinaryTree,R)
{
T->root=NewBNode();
T->root->data=x;
T->root->lchild=L->root;
T->root->rchild=R->root;
L->root=R->root=0;
}
関数BreakTree(T、L、R)は、バイナリツリー分割ルート要素Tの要素の機能MakeTree逆動作、3Lの三つの部分左サブツリー及び右サブツリーR等を実行します。
TreeItem BreakTree(BinaryTree T,BinaryTree L,BinaryTree R)
{
TreeItem x;
if(!T->root) Error("Tree is Empty!");
x=T->root->element;
L->root=T->root->lchild;
R->root=T->root->rchild;
T->root=0;
return x;
}
プリアンブル、順番に、後続のトラバーサル(再帰的)
void PreOrder(void (*visit)(btlink u),btlink t)
{
/*前序遍历*/
if(t)
{
(*visit)(t);
PreOrder(visit,t->lchild);
PreOrder(visit,t->rchild);
}
}
void InOrder(void (*visit)(btlink u),btlink t)
{
/*中序遍历*/
if(t)
{
PreOrder(visit,t->lchild);
(*visit)(t);
PreOrder(visit,t->rchild);
}
}
void PostOrder(void (*visit)(btlink u),btlink t)
{
/*后序遍历*/
if(t)
{
PreOrder(visit,t->lchild);
PreOrder(visit,t->rchild);
(*visit)(t);
}
}
前順走査(非再帰、スタックの手段によって)
//前序遍历
void PreOrderWithoutRecursion1(BTNode* root)
{
if (root == NULL)
return;
BTNode* p = root;
stack<BTNode*> s;
while (!s.empty() || p)
{
//边遍历边打印,并存入栈中,以后需要借助这些根节点(不要怀疑这种说法哦)进入右子树
while (p)
{
cout << setw(4) << p->data;
s.push(p);
p = p->lchild;
}
//当p为空时,说明根和左子树都遍历完了,该进入右子树了
if (!s.empty())
{
p = s.top();
s.pop();
p = p->rchild;
}
}
cout << endl;
}
void preorderNonrecursion(BTNode *bt)
{
if(bt!=NULL)
{
stack<BTNode*> s;
BTNode *p;
s.push(bt);
while(!IsEmpty(s))
{
p=s.pop(); //每有一个结点进栈,就执行一次弹出栈顶结点并压入其右左孩子结点的操作
visit(p);
if(p->rchild!=NULL) //记住是右子树先入栈,左子树后入栈,才能保证左子树先于右子树被访问
s.push(p->rchild);
if(p->lchild!=NULL)
s.push(p->lchild);
}
}
}
注文トラバーサルに(非再帰、スタックの手段によって)
//中序遍历
/*若栈顶结点左孩子存在,则左孩子入栈,若左孩子不存在,则输出并弹出栈顶,然后检查其右孩子是否存在,若存在则右孩子入栈*/
void InOrderWithoutRecursion1(BTNode* root)
{
//空树
if (root == NULL)
return;
//树非空
BTNode* p = root;
stack<BTNode*> s;
while (!s.empty() || p)
{
//一直遍历到左子树最下边,边遍历边保存根节点到栈中
while (p)
{
s.push(p);
p = p->lchild;
}
//当p为空时,说明已经到达左子树最下边,这时需要出栈了
if (!s.empty())
{
p = s.top();
s.pop();
cout << setw(4) << p->data;
//进入右子树,开始新的一轮左子树遍历(这是递归的自我实现)
p = p->rchild; //如果有右子树,就走while,把右子树压入栈,若无右子树,就走if,继续弹出栈顶元素
}
}
}
後順(非再帰、スタックの手段によって)
//后序遍历
//定义枚举类型:Tag
enum Tag{left,right};
//自定义新的类型,把二叉树节点和标记封装在一起
typedef struct
{
BTNode* node;
Tag tag;
}TagNode;
//后序遍历
void PostOrderWithoutRecursion2(BTNode* root)
{
if (root == NULL)
return;
stack<TagNode> s;
TagNode tagnode;
BTNode* p = root;
while (!s.empty() || p)
{
while (p)
{
tagnode.node = p;
//该节点的左子树被访问过
tagnode.tag = Tag::left;
s.push(tagnode);
p = p->lchild;
}
tagnode = s.top();
s.pop();
//左子树被访问过,则还需进入右子树
if (tagnode.tag == Tag::left)
{
//置换标记
tagnode.tag = Tag::right;
//再次入栈
s.push(tagnode);
p = tagnode.node;
//进入右子树
p = p->rchild;
}
else//右子树已被访问过,则可访问当前节点
{
cout << setw(4) << (tagnode.node)->data;
//置空,再次出栈(这一步是理解的难点),p=NULL下一层循环直接执行while(p){}后面的语句,即继续弹出栈顶
p = NULL;
}
}
cout << endl;
}
/*依据:逆后序遍历=先序遍历中左右子树访问顺序对调*/
void postordernonrecursion(BTNode *bt)
{
stack <BTNode*> s1,s2;
BTNode *p;
s1.push(bt);
while(!IsEmpty(s1))
{
p=s1.pop();
s2.push(p); //访问到的结点压入s2
if(p->lchild!=NULL)
s1.push(p->lchild);
if(p->rchild!=NULL)
s2.push(p->rchild); //先压入左子树再压入右子树,保证弹栈时先弹出右子树
}
while(!IsEmpty(s2))
{
p=s2.pop();
visit(p);
}
}
(キューを介して)レベルをトラバース
void LevelOrder(void (*visit)(btlink u),btlink t)
{
Queue q=QueueInit();
EnQueue(t,q);
while(!QueueEmpty(q))
{
(*visit)(t=DeQueue(q));
if(t->lchild) EnQueue(t->lchild,q);
if(t->rchild) EnQueue(t->rchild,q);
}
}
void Level(BTNode *bt)
{
InitQueue(Q);
BTNode *p;
EnQueue(Q,bt);
while(!IsEmpty(Q))
{
DeQueue(Q,p);
visit(p);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);
}
}
高機能は、バイナリツリーの高さを返します。
int Height(btlink t)
{
int hl,hr;
if(!t) return -1;
hl=Height(t->lchild);
hr=Height(t->rchild);
return hl>hr?++hl:++hr;//取左右子树中高度较大者的高度加上自身根结点的高度
}
サイズ関数は、バイナリツリー内のノードの数を返します
int Size(btlink t)
{
if(!t) return 0;
int lsize=Size(t->lchild);
int rsize=Size(t->rchild);
return lsize+rsize+1;//左子树结点数+右子树结点数+自身根结点数1
}