⑴ 有關二叉樹遞歸的演算法
靠,縮進全被網路搞亂了,自己排版
#include <iostream>
using namespace std;
//二叉樹節點
struct BiTreeNode{
int data;
BiTreeNode *left;
BiTreeNode *right;
};
//寫一個類,方便二叉樹的建立和刪除
class BiTree{
private:
void deleteAllNode(BiTreeNode *root);
public:
BiTreeNode *root;
BiTree();
~BiTree();
void CreateTree();
void deleteLeaves(BiTreeNode *root);
bool DepthOfTheNode(BiTreeNode *currentNode,BiTreeNode *p, int depthOfFather);
void FindMaxValue(BiTreeNode *currentNode, int *maxValue);
void ExchangeLeftAndRight(BiTreeNode *currentNode);
void OutputValueAndDepthByQIANXU(BiTreeNode *currentNode, int depthOfFather); //不好意思,用了拼音
};
BiTree::BiTree()
{
root = NULL;
}
BiTree::~BiTree()
{
deleteAllNode(root);
}
void BiTree::deleteAllNode(BiTreeNode *root)
{
if (root == NULL) return;
deleteAllNode(root->left);
deleteAllNode(root->right);
cout << root->data << ' '; //用來查看當前節點是不是被刪除。
delete root;
}
//手動建立一個二叉樹用於測試
// 1
// / \
// 2 3
// \ /
// 4 5
void BiTree::CreateTree()
{
if (root) return;
root = new BiTreeNode;
root->data = 1;
root->left = new BiTreeNode;
root->left->data = 2;
root->right = new BiTreeNode;
root->right->data = 3;
BiTreeNode *p;
p = root->left;
p->left = NULL;
p->right = new BiTreeNode;
p->right->data = 4;
p->right->left = p->right->right = NULL;
p= root->right;
p->left = new BiTreeNode;
p->left->data = 5;
p->left->left = p->left->right = NULL;
p->right = NULL;
}
//用遞歸演算法刪除葉子
void BiTree::deleteLeaves(BiTreeNode *root)
{
if (root == NULL) return;
if (!root->left && !root->right) return; //表示是根節點(或者出錯,跑到葉子節點了,這種情況應該不會),不刪除
if (root->left) //當前節點有左子樹
{
if (root->left->left || root->left->right) //左子樹不是葉子
deleteLeaves(root->left);
else //當前節點的左子節點是葉子
{
delete root->left;
root->left = NULL;
}
}
if (root->right)
{
if (root->right->left || root->right->right)
deleteLeaves(root->right);
else //當前節點的右子節點是葉子
{
delete root->right;
root->right = NULL;
}
}
}
int depth = 0; //一個用來存儲深度的全局變數,雖然在實際編程中這樣用不好
//但一切為了方便。
//節點p的深度,遞歸法
bool BiTree::DepthOfTheNode(BiTreeNode *currentNode,BiTreeNode *p, int depthOfFather)
{
if (currentNode == NULL) return false;
if (currentNode == p) //當前節點為要找的節點
{
depth = depthOfFather + 1;
return true;;
}
if (DepthOfTheNode(currentNode->left, p, depthOfFather+1)) //找當前節點的左子樹
return true;
else
return DepthOfTheNode(currentNode->right, p, depthOfFather+1);
}
//用遞歸找最大值,最大值存儲在maxValue所指的內存 ,這里使用前序遍歷
void BiTree::FindMaxValue(BiTreeNode *currentNode, int *maxValue)
{
if (currentNode == NULL) return;
*maxValue = *maxValue > currentNode->data ? *maxValue : currentNode->data;
FindMaxValue(currentNode->left, maxValue); //遍歷左子樹
FindMaxValue(currentNode->right, maxValue);
}
//交換左右,用前序遍歷
void BiTree::ExchangeLeftAndRight(BiTreeNode *currentNode)
{
if (currentNode == NULL) return;
BiTreeNode *temp;
temp = currentNode->left;
currentNode->left = currentNode->right;
currentNode->right = temp;
ExchangeLeftAndRight(currentNode->left);
ExchangeLeftAndRight(currentNode->right);
}
//以前序次序輸出一棵二叉樹所有結點的數據值及結點所在層次
void BiTree::OutputValueAndDepthByQIANXU(BiTreeNode *currentNode, int depthOfFather)
{
if (currentNode == NULL) return;
cout << "節點:" << currentNode->data;
cout << "\t深度:" << depthOfFather+1 << endl;
OutputValueAndDepthByQIANXU(currentNode->left, depthOfFather+1);
OutputValueAndDepthByQIANXU(currentNode->right, depthOfFather+1);
}
int main()
{
BiTree bt;
bt.CreateTree();
//求p的深度
bt.DepthOfTheNode(bt.root, bt.root->left->right, 0);
cout << "深度:" << depth << endl;
//找最大值
int maxValue;
bt.FindMaxValue(bt.root, &maxValue);
cout << "最大值為:" << maxValue << endl;
//交換左右節點
bt.ExchangeLeftAndRight(bt.root);
//以前序次序輸出一棵二叉樹所有結點的數據值及結點所在層次
bt.OutputValueAndDepthByQIANXU(bt.root, 0);
//刪除葉子節點
bt.deleteLeaves(bt.root);
return 0;
}
⑵ 按照二叉樹的遞歸定義,對二叉樹遍歷的常用演算法有哪三種
/*1 、前序遍歷二叉樹的遞歸演算法 */
void preorder(bintree t)
{
if (t) {
printf("%c",t->data);
preorder(t->lchild);
preorder(t->rchild);
}
}
/*2 、中序遍歷二叉樹的遞歸演算法 */
void inorder(bintree t)
{
if (t) {
inorder(t->lchild);
printf("%c",t->data);
inorder(t->rchild);
}
}
/*3 、後序遍歷二叉樹的遞歸演算法 */
void postorder(bintree t)
{
if (t) {
postorder(t->lchild);
postorder(t->rchild);
printf("%c",t->data);
}
}
⑶ 二叉樹遍歷的演算法實現
從二叉樹的遞歸定義可知,一棵非空的二叉樹由根結點及左、右子樹這三個基本部分組成。因此,在任一給定結點上,可以按某種次序執行三個操作:
⑴訪問結點本身(N),
⑵遍歷該結點的左子樹(L),
⑶遍歷該結點的右子樹(R)。
以上三種操作有六種執行次序:
NLR、LNR、LRN、NRL、RNL、RLN。
注意:
前三種次序與後三種次序對稱,故只討論先左後右的前三種次序。 根據訪問結點操作發生位置命名:
① NLR:前序遍歷(PreorderTraversal亦稱(先序遍歷))
——訪問根結點的操作發生在遍歷其左右子樹之前。
② LNR:中序遍歷(InorderTraversal)
——訪問根結點的操作發生在遍歷其左右子樹之中(間)。
③ LRN:後序遍歷(PostorderTraversal)
——訪問根結點的操作發生在遍歷其左右子樹之後。
注意:
由於被訪問的結點必是某子樹的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解釋為根、根的左子樹和根的右子樹。NLR、LNR和LRN分別又稱為先根遍歷、中根遍歷和後根遍歷。 1.先(根)序遍歷的遞歸演算法定義:
若二叉樹非空,則依次執行如下操作:
⑴ 訪問根結點;
⑵ 遍歷左子樹;
⑶ 遍歷右子樹。
2.中(根)序遍歷的遞歸演算法定義:
若二叉樹非空,則依次執行如下操作:
⑴遍歷左子樹;
⑵訪問根結點;
⑶遍歷右子樹。
3.後(根)序遍歷得遞歸演算法定義:
若二叉樹非空,則依次執行如下操作:
⑴遍歷左子樹;
⑵遍歷右子樹;
⑶訪問根結點。 用二叉鏈表做為存儲結構,中序遍歷演算法可描述為:
void InOrder(BinTree T)
{ //演算法里①~⑥是為了說明執行過程加入的標號
① if(T) { // 如果二叉樹非空
② InOrder(T->lchild);
③ printf(%c,T->data); // 訪問結點
④ InOrder(T->rchild);
⑤ }
⑥ } // InOrder 計算中序遍歷擁有比較簡單直觀的投影法,如圖
⑴在搜索路線中,若訪問結點均是第一次經過結點時進行的,則是前序遍歷;若訪問結點均是在第二次(或第三次)經過結點時進行的,則是中序遍歷(或後序遍歷)。只要將搜索路線上所有在第一次、第二次和第三次經過的結點分別列表,即可分別得到該二叉樹的前序序列、中序序列和後序序列。
⑵上述三種序列都是線性序列,有且僅有一個開始結點和一個終端結點,其餘結點都有且僅有一個前驅結點和一個後繼結點。為了區別於樹形結構中前驅(即雙親)結點和後繼(即孩子)結點的概念,對上述三種線性序列,要在某結點的前驅和後繼之前冠以其遍歷次序名稱。
【例】上圖所示的二叉樹中結點C,其前序前驅結點是D,前序後繼結點是E;中序前驅結點是E,中序後繼結點是F;後序前驅結點是F,後序後繼結點是A。但是就該樹的邏輯結構而言,C的前驅結點是A,後繼結點是E和F。
二叉鏈表基本思想
基於先序遍歷的構造,即以二叉樹的先序序列為輸入構造。
注意:
先序序列中必須加入虛結點以示空指針的位置。
【例】
建立上圖所示二叉樹,其輸入的先序序列是:ABD∮∮∮CE∮∮F∮∮。
構造演算法
假設虛結點輸入時以空格字元表示,相應的構造演算法為:
void CreateBinTree (BinTree **T){ //構造二叉鏈表。T是指向根指針的指針,故修改*T就修改了實參(根指針)本身 char ch; if((ch=getchar())=='') *T=NULL; //讀入空格,將相應指針置空 else{ //讀人非空格 *T=(BinTNode *)malloc(sizeof(BinTNode)); //生成結點 (*T)->data=ch; CreateBinTree(&(*T)->lchild); //構造左子樹 CreateBinTree(&(*T)->rchild); //構造右子樹 }}
注意:
調用該演算法時,應將待建立的二叉鏈表的根指針的地址作為實參。
示例
設root是一根指針(即它的類型是BinTree),則調用CreateBinTree(&root)後root就指向了已構造好的二叉鏈表的根結點。
二叉樹建立過程見
下面是關於二叉樹的遍歷、查找、刪除、更新數據的代碼(遞歸演算法): #include<iostream>#include<cstdio>#include<cmath>#include<iomanip>#include<cstdlib>#include<ctime>#include<algorithm>#include<cstring>#include<string>#include<vector>#include<list>#include<stack>#include<queue>#include<map>#include<set>usingnamespacestd;typedefintT;classbst{structNode{Tdata;Node*L;Node*R;Node(constT&d,Node*lp=NULL,Node*rp=NULL):data(d),L(lp),R(rp){}};Node*root;intnum;public:bst():root(NULL),num(0){}voidclear(Node*t){if(t==NULL)return;clear(t->L);clear(t->R);deletet;}~bst(){clear(root);}voidclear(){clear(root);num=0;root=NULL;}boolempty(){returnroot==NULL;}intsize(){returnnum;}TgetRoot(){if(empty())throwemptytree;returnroot->data;}voidtravel(Node*tree){if(tree==NULL)return;travel(tree->L);cout<<tree->data<<'';travel(tree->R);}voidtravel(){travel(root);cout<<endl;}intheight(Node*tree){if(tree==NULL)return0;intlh=height(tree->L);intrh=height(tree->R);return1+(lh>rh?lh:rh);}intheight(){returnheight(root);}voidinsert(Node*&tree,constT&d){if(tree==NULL)tree=newNode(d);elseif(ddata)insert(tree->L,d);elseinsert(tree->R,d);}voidinsert(constT&d){insert(root,d);num++;}Node*&find(Node*&tree,constT&d){if(tree==NULL)returntree;if(tree->data==d)returntree;if(ddata)returnfind(tree->L,d);elsereturnfind(tree->R,d);}boolfind(constT&d){returnfind(root,d)!=NULL;}boolerase(constT&d){Node*&pt=find(root,d);if(pt==NULL)returnfalse;combine(pt->L,pt->R);Node*p=pt;pt=pt->R;deletep;num--;returntrue;}voidcombine(Node*lc,Node*&rc){if(lc==NULL)return;if(rc==NULL)rc=lc;elsecombine(lc,rc->L);}boolupdate(constT&od,constT&nd){Node*p=find(root,od);if(p==NULL)returnfalse;erase(od);insert(nd);returntrue;}};intmain(){bstb;cout<<inputsomeintegers:;for(;;){intn;cin>>n;b.insert(n);if(cin.peek()=='
')break;}for(;;){cout<<inputdatapair:;intod,nd;cin>>od>>nd;if(od==-1&&nd==-1)break;b.update(od,nd);}}
⑷ 二叉樹結點的演算法
一個結點的度是指該結點的子樹個數。
度為1就是指只有1個子樹(左子樹或者右子樹)。
度為2的結點個數=葉結點個數-1=69
該二叉樹的總結點數=70+80+69=219
⑸ 二叉樹的層次遍歷演算法
二叉樹的層次遍歷演算法有如下三種方法:
給定一棵二叉樹,要求進行分層遍歷,每層的節點值單獨列印一行,下圖給出事例結構:
之後大家就可以自己畫圖了,下面給出程序代碼:
[cpp] view plain
void print_by_level_3(Tree T) {
vector<tree_node_t*> vec;
vec.push_back(T);
int cur = 0;
int end = 1;
while (cur < vec.size()) {
end = vec.size();
while (cur < end) {
cout << vec[cur]->data << " ";
if (vec[cur]->lchild)
vec.push_back(vec[cur]->lchild);
if (vec[cur]->rchild)
vec.push_back(vec[cur]->rchild);
cur++;
}
cout << endl;
}
}
最後給出完成代碼的測試用例:124##57##8##3#6##
[cpp] view plain
#include<iostream>
#include<vector>
#include<deque>
using namespace std;
typedef struct tree_node_s {
char data;
struct tree_node_s *lchild;
struct tree_node_s *rchild;
}tree_node_t, *Tree;
void create_tree(Tree *T) {
char c = getchar();
if (c == '#') {
*T = NULL;
} else {
*T = (tree_node_t*)malloc(sizeof(tree_node_t));
(*T)->data = c;
create_tree(&(*T)->lchild);
create_tree(&(*T)->rchild);
}
}
void print_tree(Tree T) {
if (T) {
cout << T->data << " ";
print_tree(T->lchild);
print_tree(T->rchild);
}
}
int print_at_level(Tree T, int level) {
if (!T || level < 0)
return 0;
if (0 == level) {
cout << T->data << " ";
return 1;
}
return print_at_level(T->lchild, level - 1) + print_at_level(T->rchild, level - 1);
}
void print_by_level_1(Tree T) {
int i = 0;
for (i = 0; ; i++) {
if (!print_at_level(T, i))
break;
}
cout << endl;
}
void print_by_level_2(Tree T) {
deque<tree_node_t*> q_first, q_second;
q_first.push_back(T);
while(!q_first.empty()) {
while (!q_first.empty()) {
tree_node_t *temp = q_first.front();
q_first.pop_front();
cout << temp->data << " ";
if (temp->lchild)
q_second.push_back(temp->lchild);
if (temp->rchild)
q_second.push_back(temp->rchild);
}
cout << endl;
q_first.swap(q_second);
}
}
void print_by_level_3(Tree T) {
vector<tree_node_t*> vec;
vec.push_back(T);
int cur = 0;
int end = 1;
while (cur < vec.size()) {
end = vec.size();
while (cur < end) {
cout << vec[cur]->data << " ";
if (vec[cur]->lchild)
vec.push_back(vec[cur]->lchild);
if (vec[cur]->rchild)
vec.push_back(vec[cur]->rchild);
cur++;
}
cout << endl;
}
}
int main(int argc, char *argv[]) {
Tree T = NULL;
create_tree(&T);
print_tree(T);
cout << endl;
print_by_level_3(T);
cin.get();
cin.get();
return 0;
}
⑹ 二叉樹演算法
二叉樹是沒有度為1的結點。
完全二叉樹定義:
若設二叉樹的高度為h,除第
h
層外,其它各層
(1~h-1)
的結點數都達到最大個數,第
h
層從右向左連續缺若干結點,這就是完全二叉樹。
完全二叉樹葉子結點的演算法:
如果一棵具有n個結點的深度為k的二叉樹,它的每一個結點都與深度為k的滿二叉樹中編號為1~n的結點一一對應,這棵二叉樹稱為完全二叉樹。
可以根據公式進行推導,假設n0是度為0的結點總數(即葉子結點數),n1是度為1的結點總數,n2是度為2的結點總數,由二叉樹的性質可知:n0=n2+1,則n=
n0+n1+n2(其中n為完全二叉樹的結點總數),由上述公式把n2消去得:n=
2n0+n1-1,由於完全二叉樹中度為1的結點數只有兩種可能0或1,由此得到n0=(n+1)/2或n0=n/2,合並成一個公式:n0=(n+1)/2
,就可根據完全二叉樹的結點總數計算出葉子結點數。
因此葉子結點數是(839+1)/2=420
⑺ 求二叉樹的基本演算法和各種遍歷演算法
#include<iostream.h>
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char TElemType;
typedef int Status;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
Status CreateBiTree(BiTree &T) //按先序次序輸入二叉樹中結點的值,構造二叉樹鏈表
{
char ch;
ch=getchar();
if(ch==' ')
T=NULL;
else
{
if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))
exit(OVERFLOW);
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
return OK;
}
Status PreOrder(BiTree T) //先序遍歷的遞歸演算法
{
if(T)
{
cout<<T->data;
PreOrder(T->lchild);
PreOrder(T->rchild);
}
return OK;
}
Status InOrder(BiTree T) //中序遍歷的遞歸演算法
{
if(T)
{
InOrder(T->lchild);
cout<<T->data;
InOrder(T->rchild);
}
return OK;
}
Status PostOrder(BiTree T) //後續遍歷的遞歸函數
{
if(T)
{
PostOrder(T->lchild);
PostOrder(T->rchild);
cout<<T->data;
}
return OK;
}
Status BiTreeLevelOrder(BiTree T) //層序遍歷的非遞歸函數
{
int front=0,rear=0;
BiTree p,Q[20];
if(T)
{
rear++;
Q[rear]=T;
}
while(front!=rear)
{
front++;
p=Q[front];
cout<<p->data;
if(p->lchild)
{
rear++;
Q[rear]=p->lchild;
}
if(p->rchild)
{
rear++;
Q[rear]=p->rchild;
}
}
return OK;
}
Status BiTreeNodeSum(BiTree T) //計算二叉樹的結點數
{
if(T==NULL)
return 0;
else
return 1+BiTreeNodeSum(T->lchild)+BiTreeNodeSum(T->rchild);
}
Status BiTreeLeafSum(BiTree T) //計算二叉樹的葉子結點數
{
if(T==NULL)
return 0;
else
if(T->lchild==NULL&&T->rchild==NULL)
return 1;
else
return BiTreeLeafSum(T->lchild)+BiTreeLeafSum(T->rchild);
}
Status BiTreeDeep(BiTree T) //計算二叉樹的深度
{
if(T==NULL)
return 0;
else
return (BiTreeDeep(T->lchild)>BiTreeDeep(T->rchild))?(BiTreeDeep(T->lchild)+1):(BiTreeDeep(T->rchild)+1);
}
void main() //主函數
{
BiTree T;
cout<<"input Bitree char:"<<endl;
CreateBiTree(T);
cout<<"先序遍歷為:"<<endl;
PreOrder(T);
cout<<endl;
cout<<"中序遍歷為:"<<endl;
InOrder(T);
cout<<endl;
cout<<"後序遍歷為:"<<endl;
PostOrder(T);
cout<<endl;
cout<<"層序遍歷為:"<<endl;
BiTreeLevelOrder(T);
cout<<endl;
BiTreeNodeSum(T);
cout<<"二叉樹的結點數:"<<BiTreeNodeSum(T)<<endl;
BiTreeLeafSum(T);
cout<<"二叉樹的葉子結點數為:"<<BiTreeLeafSum(T)<<endl;
BiTreeDeep(T);
cout<<"二叉樹的深度為:"<<BiTreeDeep(T)<<endl;
}
⑻ 二叉樹相關演算法的實驗驗證 [ 實驗目的] 驗證二叉樹的鏈接存儲結構及其上的基本操作。(c++)
淺談數據結構-二叉樹
二叉樹是樹的特殊一種,具有如下特點:1、每個結點最多有兩顆子樹,結點的度最大為2。2、左子樹和右子樹是有順序的,次序不能顛倒。3、即使某結點只有一個子樹,也要區分左右子樹。
一、特殊的二叉樹及特點
1、斜樹
所有的結點都只有左子樹(左斜樹),或者只有右子樹(右斜樹)。這就是斜樹,應用較少
基本思想:先後序遍歷左子樹,然後再後序遍歷右子樹,最後再訪問根結點即左—右—根。
圖中後序遍歷結果是:4,8,7,5,2,6,3,1。
後序遞歸遍歷代碼實現,如下所示。
後序遍歷的非遞歸實現是三種遍歷方式中最難的一種。因為在後序遍歷中,要保證左孩子和右孩子都已被訪問,並且左孩子在右孩子之前訪問才能訪問根結點,這就為流程式控制制帶來了難題。下面介紹一種思路。
要保證根結點在左孩子和右孩子訪問之後才能訪問,因此對於任一結點p,先將其入棧。若p不存在左孩子和右孩子,則可以直接訪問它,或者p存在左孩子或右孩子,但是其左孩子和右孩子都已經被訪問過了,則同樣可以直接訪問該結點。若非上述兩種情況,則將p的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候,左孩子在右孩子之前別訪問,左孩子和右孩子都在根結點前面被訪問。
五、二叉樹的建立
其實而二叉樹的建立就是二叉樹的遍歷,只不過將輸入內容改為建立結點而已,比如,利用前序遍歷建立二叉樹
⑼ 二叉樹的深度演算法怎麼算啊
二叉樹的深度演算法:
一、遞歸實現基本思想:
為了求得樹的深度,可以先求左右子樹的深度,取二者較大者加1即是樹的深度,遞歸返回的條件是若節點為空,返回0
演算法:
1
int
FindTreeDeep(BinTree
BT){
2
int
deep=0;
3
if(BT){
4
int
lchilddeep=FindTreeDeep(BT->lchild);
5
int
rchilddeep=FindTreeDeep(BT->rchild);
6
deep=lchilddeep>=rchilddeep?lchilddeep+1:rchilddeep+1;
7
}
8
return
deep;
9
}
二、非遞歸實現基本思想:
受後續遍歷二叉樹思想的啟發,想到可以利用後續遍歷的方法來求二叉樹的深度,在每一次輸出的地方替換成算棧S的大小,遍歷結束後最大的棧S長度即是棧的深度。
演算法的執行步驟如下:
(1)當樹非空時,將指針p指向根節點,p為當前節點指針。
(2)將p壓入棧S中,0壓入棧tag中,並令p執行其左孩子。
(3)重復步驟(2),直到p為空。
(4)如果tag棧中的棧頂元素為1,跳至步驟(6)。從右子樹返回
(5)如果tag棧中的棧頂元素為0,跳至步驟(7)。從左子樹返回
(6)比較treedeep與棧的深度,取較大的賦給treedeep,對棧S和棧tag出棧操作,p指向NULL,並跳至步驟(8)。
(7)將p指向棧S棧頂元素的右孩子,彈出棧tag,並把1壓入棧tag。(另外一種方法,直接修改棧tag棧頂的值為1也可以)
(8)循環(2)~(7),直到棧為空並且p為空
(9)返回treedeep,結束遍歷
1
int
TreeDeep(BinTree
BT
){
2
int
treedeep=0;
3
stack
S;
4
stack
tag;
5
BinTree
p=BT;
6
while(p!=NULL||!isEmpty(S)){
7
while(p!=NULL){
8
push(S,p);
9
push(tag,0);
10
p=p->lchild;
11
}
12
if(Top(tag)==1){
13
deeptree=deeptree>S.length?deeptree:S.length;
14
pop(S);
15
pop(tag);
16
p=NULL;
17
}else{
18
p=Top(S);
19
p=p->rchild;
20
pop(tag);
21
push(tag,1);
22
}
23
}
24
return
deeptree;
25
}
⑽ 二叉樹的遍歷演算法
這里有二叉樹先序、中序、後序三種遍歷的非遞歸演算法,此三個演算法可視為標准演算法。
1.先序遍歷非遞歸演算法
#define
maxsize
100
typedef
struct
{
Bitree
Elem[maxsize];
int
top;
}SqStack;
void
PreOrderUnrec(Bitree
t)
{
SqStack
s;
StackInit(s);
p=t;
while
(p!=null
||
!StackEmpty(s))
{
while
(p!=null)
//遍歷左子樹
{
visite(p->data);
push(s,p);
p=p->lchild;
}//endwhile
if
(!StackEmpty(s))
//通過下一次循環中的內嵌while實現右子樹遍歷
{
p=pop(s);
p=p->rchild;
}//endif
}//endwhile
}//PreOrderUnrec
2.中序遍歷非遞歸演算法
#define
maxsize
100
typedef
struct
{
Bitree
Elem[maxsize];
int
top;
}SqStack;
void
InOrderUnrec(Bitree
t)
{
SqStack
s;
StackInit(s);
p=t;
while
(p!=null
||
!StackEmpty(s))
{
while
(p!=null)
//遍歷左子樹
{
push(s,p);
p=p->lchild;
}//endwhile
if
(!StackEmpty(s))
{
p=pop(s);
visite(p->data);
//訪問根結點
p=p->rchild;
//通過下一次循環實現右子樹遍歷
}//endif
}//endwhile
}//InOrderUnrec
3.後序遍歷非遞歸演算法
#define
maxsize
100
typedef
enum{L,R}
tagtype;
typedef
struct
{
Bitree
ptr;
tagtype
tag;
}stacknode;
typedef
struct
{
stacknode
Elem[maxsize];
int
top;
}SqStack;
void
PostOrderUnrec(Bitree
t)
{
SqStack
s;
stacknode
x;
StackInit(s);
p=t;
do
{
while
(p!=null)
//遍歷左子樹
{
x.ptr
=
p;
x.tag
=
L;
//標記為左子樹
push(s,x);
p=p->lchild;
}
while
(!StackEmpty(s)
&&
s.Elem[s.top].tag==R)
{
x
=
pop(s);
p
=
x.ptr;
visite(p->data);
//tag為R,表示右子樹訪問完畢,故訪問根結點
}
if
(!StackEmpty(s))
{
s.Elem[s.top].tag
=R;
//遍歷右子樹
p=s.Elem[s.top].ptr->rchild;
}
}while
(!StackEmpty(s));
}//PostOrderUnrec