1. 程式人生 > >二叉樹的遍歷,二叉樹的建立、前序遍歷、中序遍歷、後序遍歷 (轉)

二叉樹的遍歷,二叉樹的建立、前序遍歷、中序遍歷、後序遍歷 (轉)

 // BTree.cpp : Defines the entry point for the console application.
/*
 作者:成曉旭
 時間:2001年7月2日(9:00:00-14:00:00)
 內容:完成二叉樹的建立、前序遍歷、中序遍歷、後序遍歷
 時間:2001年7月2日(14:00:00-16:00:00)
 內容:完成二叉樹的葉子節點訪問,交換左、右孩子
*/
#include "stdafx.h"
#include "stdlib.h"

#define  MAX_NODE 100
#define  NODE_COUNT1 8
#define  NODE_COUNT2 15

int TreeValue0[NODE_COUNT1][2] = {{'0',0},{'D',1},{'B',2},{'F',3},{'A',4},{'C',5},{'E',6},{'G',7}};
int TreeValue1[NODE_COUNT1][2] = {{'0',0},{'A',1},{'B',2},{'C',3},{'D',4},{'E',5},{'F',6},{'G',7}};
int TreeValue2[NODE_COUNT2][2] = {{'0',0},{'A',1},{'B',2},{'C',3},{'D',4},{'E',5},{'F',6},{'G',7},{'H',8},{'I',9},{'J',10},{'K',11},{'L',12},{'M',13},{'N',14}};
struct BTree
{
 int data;
 int order;
 BTree *lchild;
 BTree *rchild;
};

void Swap(int *p1,int *p2)
{
 int t;
 t = *p1;
 *p1 = *p2;
 *p2 = t;
}
/*
function CreateBTree()功能:建立一顆二叉樹,並返回一個指向其根的指標
*/
BTree *CreateBTree(int data[][2],int n)
{
 BTree *Addr[MAX_NODE];
 BTree *p,
    *head; 
 int nodeorder,//節點序號
  noderoot, //節點的雙親
  i;
 if(n>MAX_NODE)
 {
  printf("引數錯誤!/n");
  return(0);
 }
 for(i=1;i<=n;i++)
 {
  p = (BTree *)malloc(sizeof(BTree));
  if(p==NULL)
  {
   printf("記憶體溢位錯誤!/n");
   return(0);
  }
  else
  {
   p->data = data[i][0];
   p->lchild = NULL;
   p->rchild = NULL;
   nodeorder = data[i][1];
   p->order = nodeorder;
   Addr[nodeorder] = p;
   if(nodeorder>1)
   {
    noderoot = nodeorder/2;
    if(nodeorder %2 == 0)
     Addr[noderoot]->lchild = p;
    else
     Addr[noderoot]->rchild = p;
   }
   else
    head = p;
   printf("BTree[%d] = %c/t",p->order,p->data);
  }
  //free(p);
 }
 return(head);
}

/*
function FirstOrderAccess0()功能:實現二叉樹的前序遍歷
二叉樹前序遍歷的思想:
 從根節點開始,沿左子樹一直走到沒有左孩子的節點為止,
依次訪問所經過的節點,同時所經[節點]的地址進棧;
 當找到沒有左孩子的節點時,從棧頂退出該節點的雙親的
右孩子,此時,此節點的左子樹已訪問完畢;
 在用上述方法遍歷該節點的右子樹,如此重複到棧空為止。
*/
void FirstOrderAccess0(BTree * header)
{
 BTree * stack[MAX_NODE];
 BTree *p;
 int top;
 top = 0;
 p = header;
 do
 {
  while(p!=NULL)
  {
   printf("BTree[%d] = %c/t",p->order,p->data);//訪問節點P
   top = top+1;
   stack[top] = p;
   p = p->lchild;//繼續搜尋節點P的左子樹
  }
  if(top!=0)
  {
   p = stack[top];
   top = top-1;
   p = p->rchild;//繼續搜尋節點P的右子樹
  }
 }while((top!=0)||(p!=NULL));
}
/*
function FirstOrderAccess1()功能:實現二叉樹的前序遍歷
二叉樹前序遍歷的思想:
 從根節點開始,沿左子樹一直走到沒有左孩子的節點為止,
依次訪問所經過的節點,同時所經[節點的非空右孩子]進棧;
 當找到沒有左孩子的節點時,從棧頂退出該節點的雙親的
右孩子,此時,此節點的左子樹已訪問完畢;
 在用上述方法遍歷該節點的右子樹,如此重複到棧空為止。
*/
void FirstOrderAccess1(BTree * header)
{
 BTree * stack[MAX_NODE];
 BTree *p;
 int top;
 top = 0;
 p = header;
 do
 {
  while(p!=NULL)
  {
   printf("BTree[%d] = %c/t",p->order,p->data);
   if(p->rchild!=NULL)
    stack[++top] = p->rchild;
   p = p->lchild;
  }
  if(top!=0)
   p = stack[top--];
 }while((top>0)||(p!=NULL));
}

/*
function MiddleOrderAccess()功能:實現二叉樹的中序遍歷
二叉樹中序遍歷的思想:
 從根節點開始,沿左子樹一直走到沒有左孩子的節點為止,
並將所經[節點]的地址進棧;
 當找到沒有左孩子的節點時,從棧頂退出該節點並訪問它,
此時,此節點的左子樹已訪問完畢;
 在用上述方法遍歷該節點的右子樹,如此重複到棧空為止。
*/
void MiddleOrderAccess(BTree * header)
{
 BTree * stack[MAX_NODE];
 BTree *p;
 int top;
 top = 0;
 p = header;
 do
 {
  while(p!=NULL)
  {
   stack[++top] = p;//節點P進棧
   p = p->lchild;  //繼續搜尋其左子樹
  }
  if(top!=0)
  {
   p = stack[top--];//節點P出棧
   printf("BTree[%d] = %c/t",p->order,p->data);//訪問節點P
   p = p->rchild;//繼續搜尋其左子樹
  }
 }while((top!=0)||(p!=NULL));
}

/*
function LastOrderAccess()功能:實現二叉樹的後序遍歷
二叉樹後序遍歷的思想:
 從根節點開始,沿左子樹一直走到沒有左孩子的節點為止,
並將所經[節點]的地址第一次進棧;
 當找到沒有左孩子的節點時,此節點的左子樹已訪問完畢;
從棧頂退出該節點,判斷該節點是否為第一次進棧,如是,再
將所經[節點]的地址第二次進棧,並沿該節點的右子樹一直走到
沒有右孩子的節點為止,如否,則訪問該節點;此時,該節點的
左、右子樹都已完全遍歷,且令指標p = NULL;
 如此重複到棧空為止。
*/
void LastOrderAccess(BTree * header)
{
 BTree * stack[MAX_NODE];//節點的指標棧
 int count[MAX_NODE];//節點進棧次數陣列
 BTree *p;
 int top;
 top = 0;
 p = header;
 do
 {
  while(p!=NULL)
  {
   stack[++top] = p;//節點P首次進棧
   count[top] = 0;
   p = p->lchild;   //繼續搜尋節點P的左子樹
  }
  p = stack[top--];//節點P出棧
  if(count[top+1]==0)
  {
   stack[++top] = p;//節點P首次進棧
   count[top] = 1;
   p = p->rchild;  //繼續搜尋節點P的左子樹
  }
  else
  {
   printf("BTree[%d] = %c/t",p->order,p->data);//訪問節點P
   p = NULL;
  }
 }while((top>0));
}
/*
function IsLeafNode()功能:判斷給定二叉樹的節點是否是葉子節點
*/
int IsLeafNode(BTree *node)
{
 if((node->lchild==NULL)&&(node->rchild==NULL))
  return(1);
 else
  return(0);
}
/*
function PrintLeafNode()功能:輸出給定二叉樹的葉子節點
*/
void PrintLeafNode(BTree *header)
{
 BTree * stack[MAX_NODE];//節點的指標棧
 BTree *p;
 int top;
 p = header;
 top = 0;
 do
 {
  while(p!=NULL)
  {
   stack[++top] = p;
   p = p->lchild;//繼續搜尋節點P的左子樹
  }
  if(top!=0)
  {
   p = stack[top--];
   if(IsLeafNode(p))
    printf("LNode[%d] = %c/t",p->order,p->data);//訪問葉子節點
   p = p->rchild;//繼續搜尋節點P的右子樹
  }
 }while(top>0||p!=NULL);
}
/*
function HasTwoChildNode()功能:判斷給定二叉樹的節點是否存在兩個孩子節點
*/
int HasTwoChildNode(BTree *node)
{
 if((node->lchild!=NULL)&&(node->rchild!=NULL))
  return(1);
 else
  return(0);
}
/*
function SwapChildNode()功能:交換給定二叉樹的所有節點的左、右孩子
*/
void SwapChildNode(BTree *header)
{
 BTree * stack[MAX_NODE];//節點的指標棧
 BTree *p;
 int top;
 p = header;
 top = 0;
 do
 {
  while(p!=NULL)
  {
   stack[++top] = p;
   p = p->lchild;//繼續搜尋節點P的左子樹
  }
  if(top!=0)
  {
   p = stack[top--];
   if(HasTwoChildNode(p))
    Swap(&p->lchild->data,&p->rchild->data);//交換節點P的左、右孩子
   p = p->rchild;//繼續搜尋節點P的右子樹
  }
 }while(top>0||p!=NULL); 
}


int main(int argc, char* argv[])
{
 BTree * TreeHeader;
 printf("二叉樹建立資料結果:/n");
 TreeHeader = CreateBTree(TreeValue1,NODE_COUNT1-1);
 //TreeHeader = CreateBTree(TreeValue2,NODE_COUNT2-1);
 if (TreeHeader==0)
 {
  printf("二叉樹建立失敗!/n");
  return(0);
 }
 else
 {
  printf("/n二叉樹前序遍歷結果:/n");
  FirstOrderAccess1(TreeHeader);
  printf("/n二叉樹中序遍歷結果:/n");
  MiddleOrderAccess(TreeHeader);
  printf("/n二叉樹後序遍歷結果:/n");
  LastOrderAccess(TreeHeader);
  //printf("/n二叉樹的所有葉子節點:/n");
  //PrintLeafNode(TreeHeader);
  //SwapChildNode(TreeHeader);
  //printf("/n二叉樹交換孩子的結果:/n");
  //MiddleOrderAccess(TreeHeader);
  printf("/n程式執行完畢!/n");
  return 0;
 }
}