關於二叉樹的相關操作彙總,其中包含以下操作:
- 遞歸前序遍歷
- 非遞歸前序遍歷
- 遞歸中序遍歷
- 非遞歸中序遍歷
- 遞歸後序遍歷
- 非遞歸後序遍歷
- 遞歸層次遍歷
- 非遞歸層次遍歷
- 遞歸計算二叉樹的高度
- 非遞歸計算二叉樹高度
- 遞歸查找某點在二叉樹的那一層
- 非遞歸查找某點在二叉樹的那一層
- 判斷兩棵二叉樹是否相似
- 判斷二叉樹是不是完全二叉樹
- 輸出某一結點的到跟結點的路徑
- 得到兩個結點的最近的共同祖先
- 拆分二叉樹
- 統計二叉樹的結點個數
- 線索中序二叉樹的建立
- 線索中序二叉樹的輸出
- 根據前序和中序非遞歸建立二叉樹
- 根據前序和中序遞歸建立二叉樹
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_SIZE 100
typedef struct BiTNode{
char data;
struct BiTNode *lchild, *rchild;
}BiTNode,*BiTree;
typedef struct BiTNodeTag{
BiTNode *btnode;
int tag;
}BiTNodeTag;
typedef struct BiThrNode{
char data;
struct BiThrNode *lchild, *rchild;
int ltag,rtag;
}BiThrNode;
BiTNode *mallocTreeNode(char p){
BiTNode *temp = (BiTNode *) malloc(sizeof(BiTNode));
temp->data = p;
temp ->lchild = NULL;
temp->rchild = NULL;
return temp;
}
void printNodeData(BiTNode *nod){
printf("%c",nod->data);
}
//遞歸建立二叉樹
void createBiTree(BiTree &t){
char ch;
scanf("%c",&ch);
if (ch == ' '){
t = NULL;
return;
}
if (!(t = (BiTree)malloc(sizeof(BiTNode)))){
exit(1);
}
t->data = ch;
printf("the data is %c\n",ch);
createBiTree(t->lchild);
createBiTree(t->rchild);
}
//非遞歸建立二叉樹
BiTNode *createBiTree(){
//char str[] ="ABC@G@@@DE@@F@I";
//char str[] ="ABC@G@@@DE@@@";
//char str[] ="ABJK@@IC@G@@@";
char str[] ="ABC@G@@@DE@@@";
//char str[] ="ABC@G@@";
//char str[] ="A@B@";
//char str[] ="AB@@C@";
//char str[] ="A@B@C@";
char *p = str;
BiTNode * stack[MAX_SIZE];
int top = -1;
BiTNode *pTree = NULL;
BiTNode *rootNode = NULL;
int isRightTree = 0;
if (*p == '@'){
printf("空二叉樹");
exit(0);
}
//根節點入棧
pTree = mallocTreeNode(*p);
p++;
stack[++top] = pTree;
rootNode = pTree;
while (*p){
if (*p != '@'){
if (isRightTree){
BiTNode *temp = mallocTreeNode(*p);
pTree->rchild = temp;
pTree = temp;
//入棧
stack[++top] = pTree;
//因爲每次只能執行一次向右插入操作
isRightTree = 0;
} else {
BiTNode *temp = mallocTreeNode(*p);
pTree->lchild = temp;
pTree = temp;
//入棧
stack[++top] = pTree;
}
} else {
if (top == -1){
break;
} else {
pTree = stack[top--];
}
if (!isRightTree){
//等於@時退棧,同時向右子樹插入
isRightTree = 1;
}
}
p++;
}
return rootNode;
}
//遞歸前序遍歷
void preOrderTraverse(BiTree t){
if (t!= NULL){
printNodeData(t);
preOrderTraverse(t->lchild);
preOrderTraverse(t->rchild);
}
}
//非遞歸前序遍歷1
void preOrderTraverse1(BiTree t){
BiTNode *stack[MAX_SIZE];
int top = -1;
printNodeData(t);
BiTNode* temp = t;
stack[++top] = t;
t = t->lchild;
while(top > -1){
if (t != NULL){
printNodeData(t);
stack[++top] = t;
t = t->lchild;
}else{
//退棧操作的原因:左子樹爲空,右子樹爲空,在左子樹爲空時,直接進入退棧程序,退到上層之後訪問右子樹。
//在右子樹爲空時,說明本層的程序已經完成操作,需要退到上層繼續進行操作。
//這時候就考慮是訪問左子樹還是右子樹,因爲程序本身是訪問了左子樹之後進棧的,因此退棧後應訪問右子樹。
t = stack[top--];
//當出棧的結點爲頭結點時,因爲頭結點退棧之後,整個棧就爲空了。因此需要判斷。
if (temp == t){
t = t->rchild;
//判斷右子樹是否爲空。
if (t != NULL){
//不爲空,則進棧
stack[++top] = t;
continue;
} else{
//爲空,結束循環
break;
}
}
t = t->rchild;
}
}
}
//非遞歸前序遍歷2
void preOrderTraverse2(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
//將棧值和當前結點一起判斷,簡化了前一個方法。
while(top > -1 || p != NULL){
if (p != NULL){
printNodeData(p);
stack[++top] = p;
p = p->lchild;
} else {
p = stack[top--];
p = p->rchild;
}
}
}
//非遞歸前序遍歷3
void preOrderTraverse3(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
stack[++top] = p;
while(top >-1){
p = stack[top--];
printNodeData(p);
if(p->rchild != NULL){
stack[++top] = p->rchild;
}
if(p->lchild != NULL){
stack[++top] = p->lchild;
}
}
}
//遞歸中序遍歷
void inOrderTraverse(BiTree t){
if (t != NULL){
inOrderTraverse(t->lchild);
printNodeData(t);
inOrderTraverse(t->rchild);
}
}
//非遞歸中序遍歷
void inOrderTraverse1(BiTree t){
BiTNode *stack[MAX_SIZE];
int top = -1;
BiTNode * temp = t;
while(top > -1 || t != NULL){
while(t != NULL){
stack[++top] = t;
t = t->lchild;
}
t = stack[top--];
printNodeData(t);
t = t->rchild;
}
}
//遞歸後序遍歷
void postOrderTraverse(BiTree t){
if (t != NULL){
postOrderTraverse(t->lchild);
postOrderTraverse(t->rchild);
printNodeData(t);
}
}
//非遞歸後序遍歷1,每個結點加一個標誌位,表示該結點是第幾次在棧頂。如果是第二次則可以輸出了。如果不是,則需要訪問其右子樹。
/************************************************************************/
/* 對於任一結點P,將其入棧,然後沿其左子樹一直往下搜索,直到搜索到沒有左孩子的結點,此時該結點出現在棧頂,但是此時不能將其出棧並訪問,因此其右孩子還爲被訪問。所以接下來按照相同的規則對其右子樹進行相同的處理,當訪問完其右孩子時,該結點又出現在棧頂,此時可以將其出棧並訪問。這樣就保證了正確的訪問順序。可以看出,在這個過程中,每個結點都兩次出現在棧頂,只有在第二次出現在棧頂時,才能訪問它。因此需要多設置一個變量標識該結點是否是第一次出現在棧頂。 */
/************************************************************************/
void postOrderTraverse1(BiTree p){
BiTNodeTag *stack[MAX_SIZE];
int top = -1;
while(top > -1 || p != NULL){
while(p != NULL){
BiTNodeTag *btn=(BiTNodeTag *)malloc(sizeof(BiTNodeTag));
btn->btnode = p;
btn->tag = 1;
stack[++top]= btn;
p = p->lchild;
}
if (top >-1){
if (stack[top]->tag ==1 ){
p = stack[top]->btnode;
stack[top]->tag = 2;
p = p->rchild;
} else{
p = stack[top--]->btnode;
printNodeData(p);
//因爲要退棧,所以這裏必須要置爲空
p=NULL;
}
}
}
}
void postOrderTraverse2(BiTree p){
BiTNodeTag stack[MAX_SIZE];
int top = -1;
while(top > -1 || p != NULL){
while(p != NULL){
top++;
stack[top].btnode = p;
stack[top].tag = 1;
p = p->lchild;
}
if (top >-1){
if (stack[top].tag ==1 ){
p = stack[top].btnode;
stack[top].tag = 2;
p = p->rchild;
} else{
p = stack[top--].btnode;
printNodeData(p);
//因爲要退棧,所以這裏必須要置爲空
p=NULL;
}
}
}
}
/************************************************************************/
/* 根據特點訪問。。。要保證根結點在左孩子和右孩子訪問之後才能訪問,因此對於任一結點P,先將其入棧。如果P不存在左孩子和右孩子,則可以直接訪問它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被訪問過了,則同樣可以直接訪問該結點。若非上述兩種情況,則將P的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候,左孩子在右孩子前面被訪問,左孩子和右孩子都在根結點前面被訪問。 */
/************************************************************************/
void postOrderTraverse3(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
stack[++top] = p;//根節點入棧
BiTNode * pre = NULL; //用於記錄上次訪問結點
BiTNode * cur = NULL;
while(top >-1){
cur = stack[top];
if ((cur->lchild == NULL && cur->rchild == NULL )||(pre!= NULL &&(pre == cur->rchild || pre == cur->lchild))){
printNodeData(cur);
//訪問過之後,將這個結點移除
top--;
pre = cur;
} else {
if(cur->rchild != NULL){
stack[++top] = cur->rchild;
}
if(cur->lchild != NULL){
stack[++top] = cur->lchild;
}
}
}
}
//非遞歸後序遍歷。。 最優方法
void postOrderTraverse4(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
stack[++top] = p;
p = p->lchild;
BiTNode *pre = NULL;//之前的一個結點
while (top > -1){
//訪問左子樹
while(p != NULL){
stack[++top] = p;
p = p->lchild;
}
//每次都要將其置爲空
pre = NULL;
//這裏使用while而不使用if的原因是,
//如果使用if證明以下語句至多執行一次,而棧中有多個左子樹的結點已經訪問過。而其右子樹(多個結點)沒有訪問過。
while (top>-1){
p = stack[top];
//因爲如果pre == p->rchild即前一個結點等於當前結點的右結點,證明,當前結點的左子樹已經輸出,而且其右子樹也已經輸出,則本結點可以輸出。
//第一個輸出的是根節點
if (pre == p->rchild){
top--;
printNodeData(p);
pre = p;
}else {
//如果不是,則訪問右子樹。
p = p->rchild;
break;
}
}
}
}
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
//遞歸層次遍歷,使用隊列
void levelOrderTraverse(BiTree p){
if (p == NULL){
return;
}
printNodeData(p);
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
}
p = queue[front++];
levelOrderTraverse(p);
}
void printDataByLevel(BiTNode *p, int i,int n);
int countLevelOfBiTree2(BiTree p);
//按照層次遍歷,不使用隊列
void levelOrderTraverse1(BiTree p){
int level = countLevelOfBiTree2(p);
int i = 1 ;
for (i= 1;i<=level;i++){
printDataByLevel(p,i,1);
}
}
//按照層次打印
void printDataByLevel(BiTNode *p, int i,int n){
if (p == NULL){
return;
}
if (i == n){
printNodeData(p);
}
printDataByLevel(p->lchild,i,n+1);
printDataByLevel(p->rchild,i,n+1);
}
//非遞歸層次遍歷
void levelOrderTraverse2(BiTree p){
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
queue[rear++] = p;
while(front != rear){
p = queue[front++];
printNodeData(p);
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
}
}
}
//遞歸求二叉樹高度
int countLevelOfBiTree1(BiTree p){
if (p == NULL){
return 0;
}
int lel = countLevelOfBiTree1(p->lchild);
int ler = countLevelOfBiTree1(p->rchild);
return lel > ler ? lel +1: ler+1;
}
//非遞歸求二叉樹的高度,在非遞歸層次遍歷基礎上修改
/************************************************************************/
/* 因爲訪問完一層之後,這一層所有結點的子節點也已經完全進入隊列。
* 根據這個特點來計算二叉樹層次
* 我們使用visitedNumber表示出棧的元素的下標,enQueNumber表示進棧元素的下標,lastNumberOfOneLevel表示一層當中最後一個元素的下標
* 每次訪問結點時:visitedNumber+1,進棧時:enQueNumber+1,當一層所有的元素都出棧時lastNumberOfOneLevel=下一層最後一個元素的下標。
*
*/
/************************************************************************/
int countLevelOfBiTree2(BiTree p){
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
queue[rear++] = p;
int visitedNumber = 0;
int enQueNumber = 1; //當前入棧的序號,root爲1
int lastNumberOfOneLevel = 1; //因爲已經有一個入隊列
int height = 0;
while(front != rear){
p = queue[front++];
visitedNumber++;
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
enQueNumber++;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
enQueNumber++;
}
if (lastNumberOfOneLevel == visitedNumber){
height ++;
lastNumberOfOneLevel = enQueNumber;
}
}
return height;
}
//求一點在樹的那層。非遞歸形式,
int getLevelOfOneNodeInBiTree(BiTree p,char item){
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
queue[rear++] = p;
int visitedNumber = 0;
int enQueNumber = 1; //當前入棧的序號,root爲1
int lastNumberOfOneLevel = 1; //因爲已經有一個入隊列
int height = 0;
while(front != rear){
p = queue[front++];
visitedNumber++;
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
enQueNumber++;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
enQueNumber++;
}
if (lastNumberOfOneLevel == visitedNumber){
height ++;
lastNumberOfOneLevel = enQueNumber;
}
if (item == p->data){
if (lastNumberOfOneLevel < enQueNumber){
return height + 1;
} else {
return height;
}
}
}
return -1;
}
//求一點在樹的那層。遞歸形式
void getLevelOfOneNodeInBiTree2(BiTree p,char item,int i,int *n){
if (p == NULL){
return;
}
if (item == p->data){
*n = i;
} else {
getLevelOfOneNodeInBiTree2(p->lchild,item,i+1,n);
getLevelOfOneNodeInBiTree2(p->rchild,item,i+1,n);
}
}
//遞歸判斷兩棵二叉樹是否相似
int similarBiTree(BiTree p1,BiTree p2){
if (p1 == NULL && p2 == NULL){
return 1;
} else if (p1 == NULL || p2 == NULL){
return 0;
} else {
return(similarBiTree(p1->rchild,p2->rchild)*similarBiTree(p1->lchild,p2->lchild));
}
}
/************************************************************************/
/*判斷一棵二叉樹是不是完全二叉樹。
*分爲兩種情況:
*一、二叉樹採用順序存儲方式,這種方式中,只從前向後判斷沒有空節點即可。
*
*二、樹採用鏈表形式進行存儲,這個時候,只要對二叉樹按層進行遍歷判斷:
*
*1、某結點沒有左孩子,則一定沒有右孩子。
*2、某結點如果沒有左孩子或右孩子,那麼其後序結點一定沒有孩子。
*/
/************************************************************************/
int fullBiTree(BiTree p){
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
queue[rear++] = p;
int haveChild = 1;
while(front != rear){
p = queue[front++];
if (p->lchild == NULL && p->rchild != NULL){
return 0;
}
if (!haveChild && (p->lchild != NULL || p->rchild != NULL)){
return 0;
}
if (p->lchild == NULL || p->rchild == NULL ){
haveChild = 0;
}
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
}
}
return 1;
}
//輸出根節點到P結點的路徑
//採用非遞歸後序形式判斷,當輸出元素與結點元相同時,棧中的所有元素就是路徑。
void printPath(BiTree p , char s){
BiTNode *stack[MAX_SIZE];
int top = -1;
stack[++top] = p;
p = p->lchild;
BiTNode * pre=NULL;
while (top >-1){
while (p != NULL){
stack[++top] = p;
p = p->lchild;
}
pre = NULL;
while (top>-1){
p = stack[top];
if (p ->rchild == pre){
//找到這個結點了,將這時棧中的所有元素輸出。
if(p->data == s){
while(top>-1){
printNodeData(stack[top--]);
}
break;
}
top--;
pre = p;
} else {
p= p->rchild;
break;
}
}
}
}
//得到兩個結點的最近的共同祖先
/************************************************************************/
/*
採用非遞歸後序形式判斷,當輸出元素與結點元相同時,棧中的所有元素就是該元素的路徑。
設置一個對每個結點設置一個標誌位,標識是否是一個元素的祖先結點,當是祖先結點時,
將該標誌位設置爲1,當第二個元素再次訪問該標誌位時如果是0,則將其設置爲1,如果爲1
表示,當前結點是另外一個節點的祖先結點,因此將其輸出即可。
注意:遍歷棧中的元素時採用從棧頂到棧尾的方式遍歷。
*/
/************************************************************************/
char getAncestorOfTwoNode(BiTree p,char p1,char p2){
BiTNodeTag stack[MAX_SIZE];
int top = -1;
top++;
stack[top].btnode = p;
stack[top].tag = 0;
p = p->lchild;
BiTNode * pre = NULL;
int i = 0;
while(top > -1){
while(p != NULL){
top++;
stack[top].btnode = p;
stack[top].tag = 0;
p = p->lchild;
}
pre = NULL;
while(top > -1){
p = stack[top].btnode;
//判斷是否是第二次入棧
if (pre == p ->rchild){
//printNodeData(p);
if (p->data == p1 || p->data == p2){
for (i = top;i >= 0;i--){
if (stack[i].tag == 0){
stack[i].tag = 1;
} else {
return (stack[i].btnode)->data;
}
}
}
top--;
pre = p;
} else {
p = p->rchild;
break;
}
}
}
return '-';
}
//拆分二叉樹,輸入一個節點值,將以這個值爲根節點的樹分爲兩個樹。
BiTNode* disLink(BiTNode **p,char data){
BiTNode *stack[MAX_SIZE];
int top = -1;
BiTNode *t = NULL;
while (top > -1 || *p != NULL){
if (p != NULL){
//printNodeData(*p);
if (data == (*p)->data){
t = *p;
p = NULL;
break;
}
stack[++top] = *p;
*p = (*p)->lchild;
} else {
*p = stack[top--];
*p = (*p)->rchild;
}
}
return t;
}
//統計二叉樹的結點個數。遍歷二叉樹即可
int countNodes(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
int count = 0;
while(p != NULL || top>-1){
while(p != NULL){
stack[++top] = p;
p = p->lchild;
}
if (top>-1){
p = stack[top--];
// printNodeData(p);
count++;
p=p->rchild;
}
}
return count;
}
/*******************************線索二叉樹相關操作開始********************************************/
//創建中序的線索二叉樹,對其進行線索化。
BiThrNode * inOrderTreading(BiThrNode *p){
BiThrNode* stack[MAX_SIZE];
int top = -1;
BiThrNode* pre = NULL;
BiThrNode *root = p;
while(top > -1 || p != NULL){
while (p != NULL){
stack[++top] = p;
p = p ->lchild;
}
if (top > -1){
p = stack[top--];
//證明這是第一個結點
if (pre == NULL){
p->lchild = NULL;
}else{
//建立後記線索
if (pre ->rchild == NULL){
pre ->rtag = 1;
pre->rchild = p;
}
//建立前驅線索
if (p->lchild == NULL){
p ->lchild = pre;
p->ltag = 1;
}
}
//設置前前一個結點。
pre = p;
//printf("%c",p->data);
p = p->rchild;
} else {
break;
}
}
return root;
}
//申請一個線索二叉樹結點
BiThrNode * mallocBiThrNode(char s){
BiThrNode *root = (BiThrNode *)malloc(sizeof(BiThrNode));
root->data = s;
root->lchild = NULL;
root->rchild = NULL;
root->ltag = 0;
root->rtag = 0;
return root;
}
//構建線索二叉樹
BiThrNode * createThrTree(){
char str[] ="ABC@G@@@DE@@@";
char *ps = str;
BiThrNode *stack[MAX_SIZE];
int top = -1;
if (*ps == '@'){
printf("空線索二叉樹");
exit(0);
}
BiThrNode *root = mallocBiThrNode(*ps);
ps++;
stack[++top] = root;
BiThrNode *p = root;
BiThrNode *temp ;
int rl = 1;
while(*ps != '\0'){
if (*ps != '@'){
if (rl == 1){
temp = mallocBiThrNode(*ps);
p->lchild = temp;
p = temp;
stack[++top] = p;
} else {
temp = mallocBiThrNode(*ps);
p->rchild = temp;
p = temp;
stack[++top] = p;
rl = 1;
}
} else {
if (rl == 1){
rl = 2;
}
if (top > -1){
p = stack[top--];
} else {
break;
}
}
ps++;
}
return root;
}
//找到某個結點的後繼結點
BiThrNode * succ(BiThrNode * p){
if (p->rtag == 1){
return p->rchild;
} else {
//中序遍歷特點LDR,後繼結點當前結點處於D處,因爲已經訪問到當前結點了。
//所以需要從右子樹找後繼結點,從LDR的特點來看,這個結點就是右子樹的最左側的那個節點。
//爲什麼要使用ltag呢,因爲,所有的lchild屬性都已經使用了。
if ((p = p->rchild)!= NULL){
while(p->ltag == 0){
p = p->lchild;
}
}
return p;
}
}
//找到某個樹的前驅結點
BiThrNode * pre(BiThrNode *p){
if (p->ltag == 1){
return p->lchild;
} else {
//中序遍歷特點LDR,後繼結點當前結點處於D處,因爲已經訪問到當前結點了。
//所以需要從左子樹找前驅結點,從LDR的特點來看,這個結點就是左子樹的最右側的那個節點。
//p = p->lchild;
if ((p = p->lchild) != NULL){
while(p->rtag == 0){
p = p->rchild;
}
}
return p;
}
}
//非遞歸輸出中序遍歷線索二叉樹
void inOrderTraverseThrTree(BiThrNode * p){
BiThrNode * temp;
//LDR中序遍歷,先找前序結點
while(p != NULL){
temp = p;
p = pre(p);
}
p = temp;
while(p != NULL){
printf("%c",p->data);
p = succ(p);
}
}
/*******************************線索二叉樹相關操作結束********************************************/
typedef struct BiTreeNode{
//保存原始值
char s;
//是否訪問過
int flag;
//
BiTNode *p;
}BiTreeNode;
int getPositionOfNode(char s, BiTreeNode *nodes,int len);
int getPostionBetweenPos1AndPos2(int pos1, int pos2,BiTreeNode *nodes);
//由前序和中序序列得到二叉樹,非遞歸
//實際上,只要將後序序列,前後調換順序,得到的二叉樹是一樣的。因此,後序就不再寫了。
BiTNode * getBiTreeByPreAndIn(char * p1,char *p2){
int len = strlen(p2);
BiTreeNode *nodes = new BiTreeNode[len];
int i = 0;
//初始化
for (i = 0;i < len ;i++){
nodes[i].s = *(p2+i);
nodes[i].flag = 0;
nodes[i].p = (BiTNode *)malloc(sizeof(BiTNode));
nodes[i].p->data = *(p2+i);
nodes[i].p->lchild = NULL;
nodes[i].p->rchild = NULL;
}
BiTNode *root = NULL;
//後序和中序時,讀出後序的最後一個在中序中找到並標識
for (i = 0;i<len;i++){
//將根節點設置爲已讀
if (nodes[i].p->data == *p1){
nodes[i].flag = 1;
root = nodes[i].p;
}
}
//後序時,只要將其i從大往小遞減即可
for (i = 0;i<len-1;i++){
int pos1 = getPositionOfNode(p1[i],nodes,len);
int pos2 = getPositionOfNode(p1[i+1],nodes,len);
int pos3 = getPostionBetweenPos1AndPos2(pos1,pos2,nodes);
//設置爲已讀
nodes[pos2].flag = 1;
if (pos3 > pos2){
nodes[pos3].p->lchild = nodes[pos2].p;
} else {
nodes[pos3].p->rchild = nodes[pos2].p;
}
}
return root;
}
int getPositionOfNode(char s, BiTreeNode *nodes,int len){
int i = 0;
for (i = 0;i<len;i++){
if (s == nodes[i].s){
return i;
}
}
}
int getPostionBetweenPos1AndPos2(int pos1, int pos2,BiTreeNode *nodes){
int i = 0;
//得到pos1和pos2之間離pos2最近的已經訪問過的那個結點的位置。
if (pos1 > pos2){
for (i=pos2;i<=pos1;i++){
if (nodes[i].flag ==1){
return i;
}
}
} else {
for (i = pos2;i>=pos1;i--){
if (nodes[i].flag ==1){
return i;
}
}
}
}
//由前序和中序序列得到二叉樹,遞歸
BiTNode * getBiTreeByPreAndIn2(char * ppos,char *ipos,int n){
BiTNode *ptr;
char *rpos;
int k;
if (n <= 0){
return NULL;
}
ptr = (BiTNode*)malloc(sizeof(BiTNode));
ptr->data = *ppos;
for (rpos = ipos;rpos <ipos+n;rpos++){
if (*rpos == *ppos){
break;
}
}
//根結點的位置
k = rpos -ipos;
ptr->lchild = getBiTreeByPreAndIn2(ppos+1,ipos,k);
ptr->rchild = getBiTreeByPreAndIn2(ppos+1+k,rpos+1,n-1-k);
return ptr;
}
void main(){
BiTNode * root = createBiTree();
printf("前序遍歷:\n");
preOrderTraverse(root);
printf("\n");
preOrderTraverse1(root);
printf("\n");
preOrderTraverse2(root);
printf("\n");
preOrderTraverse3(root);
printf("\n\n");
printf("中序遍歷:\n");
inOrderTraverse(root);
printf("\n");
inOrderTraverse1(root);
printf("\n\n");
printf("後序遍歷:\n");
postOrderTraverse(root);
printf("\n");
postOrderTraverse1(root);
printf("\n");
postOrderTraverse2(root);
printf("\n");
postOrderTraverse3(root);
printf("\n");
postOrderTraverse4(root);
printf("\n\n");
printf("層次遍歷:\n");
levelOrderTraverse(root);
printf("\n");
levelOrderTraverse1(root);
printf("\n");
levelOrderTraverse2(root);
printf("\n\n");
printf("二叉樹的高度:\n");
printf("the level is %d\n",countLevelOfBiTree1(root));
printf("the level is %d\n",countLevelOfBiTree2(root));
printf("\n");
printf("查找某點在二叉樹的那一層:\n");
printf("the level of %c in BiTree is %d\n",'E',getLevelOfOneNodeInBiTree(root,'E'));
int i = 0;
getLevelOfOneNodeInBiTree2(root,'E',1,&i);
printf("the level of %c in BiTree is %d",'E',i);
printf("\n\n");
printf("判斷兩棵二叉樹是否相似:\n");
printf("%d",similarBiTree(createBiTree(),createBiTree()));
printf("\n\n");
printf("判斷二叉樹是不是完全二叉樹:\n");
printf("the tree is full tree %d",fullBiTree(root));
printf("\n\n");
printf("輸出某一結點的到跟結點的路徑:\n");
printf("The path of the itme is ");
printPath(root,'D');
printf("\n\n");
printf("得到兩個結點的最近的共同祖先: \n");
printf("The common item is %c",getAncestorOfTwoNode(root,'C','G'));
printf("\n\n");
//printf("拆分二叉樹: \n");
//preOrderTraverse(disLink(&root,'B'));
//printf("\n");
////指針沒掌握好,沒調試出來。
//preOrderTraverse(root);
//printf("\n\n");
printf("統計二叉樹的結點個數:\n");
printf("The count of the BinTree is %d",countNodes(root));
printf("\n\n");
printf("線索中序二叉樹的建立和輸出:\n");
BiThrNode *thRoot = inOrderTreading(createThrTree());
inOrderTraverseThrTree(thRoot);
printf("\n\n");
printf("根據前序和中序建立二叉樹:\n");
postOrderTraverse4(getBiTreeByPreAndIn("abdgcefhi","dgbaechif"));
printf("\n");
postOrderTraverse4(getBiTreeByPreAndIn2("abdgcefhi","dgbaechif",9));
printf("\n");
}