/* 二叉樹後根周遊的非遞歸算法*/
#include "stdafx.h"
#include<stdlib.h>
#include<stdio.h>
typedef char DataType;
struct BinTreeNode; /* 二叉樹中結點 */
typedef struct BinTreeNode *PBinTreeNode; /* 結點的指針類型 */
int inum=0;
struct BinTreeNode {
DataType info; /* 數據域 */
PBinTreeNode llink; /* 指向左子女 */
PBinTreeNode rlink; /* 指向右子女 */
};
typedef struct BinTreeNode *BinTree;
typedef BinTree *PBinTree;
typedef PBinTreeNode BNode;
PBinTreeNode root_btree(PBinTree t) {
return *t;
}
PBinTreeNode leftChild_btree (PBinTreeNode p){
return p->llink;
}
PBinTreeNode rightChild_btree (PBinTreeNode p){
return p->rlink;
}
/*以下算法就是先將二叉樹擴充爲擴充的二叉樹,
然後按先根次序周遊的順序輸入結點的信息,
生成一個雙鏈存儲的二叉樹的過程*/
/*
PBinTreeNode create(PBinTreeNode t,int c)
{
PBinTreeNode p,di; // p用來指向所要分配的結點,di用來指向p的雙親
do{ // do—while結構用來構造二叉數,直到輸入0爲止
scanf("%d",&c); // 輸入葉子結點的數據
if (t==0) // 如果這是創建的第一個結點(根),則t指向這個結點(根)
{
t=(PBinTreeNode)malloc(sizeof(PBinTreeNode));
t->llink=t->rlink=0;
t->info=c;
}
else // 否則,按二叉排序樹的構造方法構造樹
{ p=t; // 先讓p指向根
while(p!=0) // 如果p 不空,則按二叉排序樹的查找順序來查找新的結點位置
{
di=p; // 在p指向下一個結點之前,用di保存當前p的位置
if(c<(p->info)) // 如果輸入的結點比p指向的結點小
p=p->llink; // p指向當前p的左孩子
else
p=p->rlink; // 否則p指向當前p的右孩子
}
// 此處已經退出 while(p!=0) 這個循環,表明已經找到輸入的結點合適的位置了,
// 這個位置或者是di的左孩子,或者是di的右孩子
if(c<(di->info)) // 如果輸入的結點比di小,將輸入的結點添加在di左孩子
{
PBinTreeNode NEWdi=(PBinTreeNode) malloc(sizeof(PBinTreeNode));
NEWdi->llink=NEWdi->rlink=0;
NEWdi->info=c;
di->llink=NEWdi;
}
else // 否則將輸入的結點添加在di的又孩子
{
PBinTreeNode NEWdi=(PBinTreeNode) malloc(sizeof(PBinTreeNode));
NEWdi->llink=NEWdi->rlink=0;
NEWdi->info=c;
di->rlink=NEWdi;
}
}
++number; // 結點數+1
}while(c!=0);
printf("葉子的數量:%d",number);
return t;
} */
PBinTreeNode createRest_BTree() {
/* 遞歸創建從根開始的二叉樹 */
//PBinTreeNode pbnode;
//char ch;
//int i=0;
//scanf("%c",&ch);
//if ( ch == '@') pbnode = NULL;
//else {
// inum++;
// //if (inum>6) return pbnode;
// pbnode = (PBinTreeNode )malloc(sizeof(struct BinTreeNode));
// if (pbnode == NULL) {
// printf("Out of space!/n");
// return pbnode;
// }
// pbnode->info = ch;
// pbnode->llink = createRest_BTree(); /* 構造左子樹 */
// pbnode->rlink = createRest_BTree(); /* 構造右子樹 */
//}
//return pbnode;
int c=1;
int number=0;
PBinTreeNode t=0;
PBinTreeNode p,di; // p用來指向所要分配的結點,di用來指向p的雙親
do{ // do—while結構用來構造二叉數,直到輸入0爲止
scanf("%d",&c); // 輸入葉子結點的數據
if (t==0) // 如果這是創建的第一個結點(根),則t指向這個結點(根)
{
t=(PBinTreeNode)malloc(sizeof(PBinTreeNode));
t->llink=t->rlink=0;
t->info=c;
}
else // 否則,按二叉排序樹的構造方法構造樹
{ p=t; // 先讓p指向根
while(p!=0) // 如果p 不空,則按二叉排序樹的查找順序來查找新的結點位置
{
di=p; // 在p指向下一個結點之前,用di保存當前p的位置
if(c<(p->info)) // 如果輸入的結點比p指向的結點小
p=p->llink; // p指向當前p的左孩子
else
p=p->rlink; // 否則p指向當前p的右孩子
}
// 此處已經退出 while(p!=0) 這個循環,表明已經找到輸入的結點合適的位置了,
// 這個位置或者是di的左孩子,或者是di的右孩子
if(c<(di->info)) // 如果輸入的結點比di小,將輸入的結點添加在di左孩子
{
PBinTreeNode NEWdi=(PBinTreeNode) malloc(sizeof(PBinTreeNode));
NEWdi->llink=NEWdi->rlink=0;
NEWdi->info=c;
di->llink=NEWdi;
}
else // 否則將輸入的結點添加在di的又孩子
{
PBinTreeNode NEWdi=(PBinTreeNode) malloc(sizeof(PBinTreeNode));
NEWdi->llink=NEWdi->rlink=0;
NEWdi->info=c;
di->rlink=NEWdi;
}
}
++number; // 結點數+1
}while(c!=0);
printf("葉子的數量:%d",number);
return t;
}
PBinTree create_BTree( void ) {
/* 創建完整的二叉樹 */
int i=0;
PBinTree pbtree = (PBinTree)malloc(sizeof(BinTree));
if (i<1){
i++;
if (pbtree != NULL)
/*{
i++;
}*/
*pbtree = createRest_BTree( ); /* 遞歸創建從根開始的二叉樹 */
}
return pbtree;
}
void visit(BNode p) {
//printf("%c ",p->info); }
printf("%d ",p->info);
}
typedef struct {
BNode ptr; /* 進棧結點 */
int tag; /* 標記 */
} Elem;
/*棧順序表示*/
#define MAXNUM 20 /* 棧中最大元素個數 */
struct SeqStack { /* 順序棧類型定義 */
int t; /* 指示棧頂位置 */
Elem s[MAXNUM];
};
typedef struct SeqStack *PSeqStack; /* 順序棧類型的指針類型 */
/*創建一個空棧;爲棧結構申請空間,並將棧頂變量賦值爲-1*/
PSeqStack createEmptyStack_seq( void ) {
PSeqStack pastack;
pastack = (PSeqStack)malloc(sizeof(struct SeqStack));
if (pastack == NULL)
printf("Out of space!! /n");
else
pastack->t = -1;
return pastack;
}
/*判斷pastack所指的棧是否爲空,爲空棧時返回1,否則返回0*/
int isEmptyStack_seq( PSeqStack pastack ) {
return pastack->t == -1;
}
/* 在棧中壓入一元素x */
void push_seq( PSeqStack pastack, Elem x ) {
if( pastack->t >= MAXNUM - 1 )
printf( "Overflow! /n" );
else {
pastack->t++;
pastack->s[pastack->t] = x;
}
}
/* 刪除棧頂元素 */
void pop_seq( PSeqStack pastack ) {
if (pastack->t == -1 )
printf( "Underflow!/n" );
else
pastack->t--;
}
/* 假定pastack所指的棧不爲空,求棧頂元素的值 */
Elem top_seq( PSeqStack pastack ) {
return (pastack->s[pastack->t]);
}
void nPostOrder(PBinTree t) {
PSeqStack st; /* 棧中元素類型爲 Elem */
Elem stnode;
BNode p; /* 周遊時當前要處理的結點*/
char continueflag; /* 表明是否繼續退棧,從右子樹返回時訪問完根之後需繼續退棧 */
if (*t == NULL) return;
st = createEmptyStack_seq( ); /* 創建空棧 */
p = *t; /* 從根結點開始 */
do { /* 每執行一次大循環進入一棵由p指出根的子樹去周遊 */
while (p != NULL) { /* 反覆地把遇到的結點進棧並進入它的左子樹 */
stnode.ptr = p;
stnode.tag = 1;
push_seq(st, stnode);
p = leftChild_btree(p);
}
continueflag = 't';
while ( continueflag == 't' && !isEmptyStack_seq(st) ) {
stnode = top_seq(st);
pop_seq(st); /* 退棧 */
p = stnode.ptr;
if (stnode.tag == 1) {
/* 如果是從左子樹回來,則改標誌重新進棧,停止退棧並進入右子樹 */
stnode.tag = 2;
push_seq(st, stnode);
continueflag = 'f';
p = rightChild_btree(p);
}
else visit(p);
}
} while (!isEmptyStack_seq (st)); /* 棧爲空時,全部周遊完 */
}
int main(){
PBinTree PBinTreeNode = create_BTree();
nPostOrder(PBinTreeNode);
putchar('/n');
return 0;
}