#include<stdio.h>
#include<stdlib.h>
#include"squeue.h"
#define Status int
#define OK 1
Status CreateBiTree(BiTree *T)
{
char ch;
scanf("\n%c", &ch);
if (ch == '#')
*T = NULL;
else
{
(*T) = (BiTree)malloc(sizeof(BiTNode));
(*T)->data = ch;
printf("输入%c的左子结点:", ch);
CreateBiTree(&(*T)->lchild);
printf("输入%c的右子结点:", ch);
CreateBiTree(&(*T)->rchild);
}
return OK;
}
void PreOrderTraverse(BiTree T)
{
if (T == NULL) return;
printf(" %2c ", T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
void InOrderTraverse(BiTree T)
{
if (T == NULL) return;
InOrderTraverse(T->lchild);
printf(" %2c ", T->data);
InOrderTraverse(T->rchild);
}
void PostOrderTraverse(BiTree T)
{
if (T == NULL) return;
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf(" %2c ", T->data);
}
//叶子数
int LeafCount(BiTree T)
{
int num1, num2;
if (T == NULL) return 0;
else if (T->lchild == NULL&&T->rchild == NULL) return 1;
else
{
num1 = LeafCount(T->lchild);
num2 = LeafCount(T->rchild);
return (num1 + num2);
}
}
//树的深度
int TreeDeep(BiTree T)
{
int deep = 0;
if (T)
{
int LeftDeep = TreeDeep(T->lchild);
int RightDeep = TreeDeep(T->rchild);
deep = LeftDeep > RightDeep ? LeftDeep + 1 : RightDeep + 1;
}
return deep;
}
BiTNode *Swap(BiTree T)
{//交换左右子树,不破坏原二叉树
BiTree t, t1, t2;
if (T == NULL) t = NULL;
else
{
t = (BiTree)malloc(sizeof(BiTNode));
t->data = T->data;
t1 = Swap(T->lchild);
t2 = Swap(T->rchild);
t->lchild = t2;
t->rchild = t1;
}
return t;
}
void InOrderTraverse2(BiTree T)
{
SqStack S;
BiTree p;
InitStack(&S);//栈初始化
p = T;
while (p != NULL||S.top!=-1)
{
if (p != NULL)
{
Push(&S, p);
p = p->lchild;
}
else
{
p=Pop(&S);
printf(" %2c ", p->data);
p = p->rchild;
}
}
}
void CopyTree(BiTree S, BiTree *P)
{
if (S == NULL)
*P = NULL;
else
{
*P = (BiTree)malloc(sizeof(BiTNode));
(*P)->data = S->data;
CopyTree(S->lchild, &(*P)->lchild);
CopyTree(S->rchild, &(*P)->rchild);
}
}
int main()
{
int cord,deep,N;
BiTree T, P,M;
do
{
printf("\n\n1.创建二叉树\n");
printf("2.先序遍历\n");
printf("3.中序遍历\n");
printf("4.后序遍历\n");
printf("5.叶子数\n");
printf("6.树的深度\n");
printf("7.交换左右子树\n");
printf("8.非递归中序遍历\n");
printf("9.二叉树复制\n");
scanf("%d", &cord);
switch (cord)
{
case 1:
{printf("输入根节点的值,#表示没有叶结点\n");
if (CreateBiTree(&T))printf("创建成功\n");
}break;
case 2:{printf("先序遍历二叉树:\n"); PreOrderTraverse(T); }break;
case 3:{printf("中序遍历二叉树:\n"); InOrderTraverse(T); }break;
case 4:{printf("后序遍历二叉树:\n"); PostOrderTraverse(T); }break;
case 5:{N = LeafCount(T); printf("树的叶子结点个数为:%d", N); }break;
case 6:{deep = TreeDeep(T); printf("\n树的深度为%d ", deep); }break;
case 7:{
P = Swap(T);
printf("交换后的前序遍历为:\n");
PreOrderTraverse(P);
printf("\n交换后的中序遍历为:\n");
InOrderTraverse(P);
}break;
case 8:
{
printf("非递归的中序遍历为:\n");
InOrderTraverse2(T);
}break;
case 9:
{
CopyTree(T, &M);
PreOrderTraverse(M);
}break;
}
} while (cord < 9);
return 0;
}
//squeue.h
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 30
typedef struct BiTNode
{
char data;
struct BitNode *lchild, *rchild;
}BiTNode, *BiTree;
typedef struct SqStack
{
BiTNode *data[MAXSIZE];
int top;
}SqStack;
void InitStack(SqStack *S)
{
S->top = -1;
}
void Push(SqStack *S,BiTNode *x)
{
if (S->top == MAXSIZE - 1){ printf("栈满无法入栈\n"); }
else
{
S->top++;
S->data[S->top] = x;
}
}
BiTNode *Pop(SqStack *S)
{
BiTNode *x;
if (S->top == -1)
{
printf("栈是空的\n"); return NULL;
}
else
{
x = S->data[S->top];
S->top--;
return x;
}
}
线索化二叉树
if(!p->lchild)表示如果某结点的左指针域为空,因为其前驱结点刚刚访问过,赋值了pre,所以可以将pre赋值给p->lchild,并修改p->ltag = Thread(也就是定义为1)以完成前驱结点的线索化。
后继就麻烦一些。因为此时p结点的后继还没有访问到,因此只能对它的前驱结点pre的右指针rchild做判断,if(!pre->rchild)表示如果为空,则p就是pre的后继,于是pre->rchild = p,并且设置pre->rtag = Thread,完成后继结点的线索化。
完成前驱和后继的判断后,不要忘记当前结点p赋值给pre,以便于下一次使用。
#include<stdio.h>
#include<stdlib.h>
#define Status int
#define OK 1
typedef enum {Link, Thread }PointerTag;
typedef struct BiThrNode
{
char data;
struct BiThrNode *lchild, *rchild;
PointerTag LTag, RTag;
}BiThrNode,*BiThrTree;
BiThrTree pre;
Status Create(BiThrTree *T)
{
char ch;
scanf("\n%c", &ch);
if (ch == '#')
*T = NULL;
else
{
*T = (BiThrTree)malloc(sizeof(BiThrNode));
(*T)->data = ch;
printf("输入%c的左子节点:", ch);
Create(&(*T)->lchild);
printf("输入%c的右子节点:", ch);
Create(&(*T)->rchild);
}
return OK;
}
void InThreading(BiThrTree p)
{
if (p)
{
InThreading(p->lchild);//递归左子树线索化
if (!p->lchild )
{
p->LTag = Thread;
p->lchild = pre;//左孩子指针指向前驱
}
else p->LTag = 0;
if (!pre->rchild)//前驱没有右孩子
{
pre->RTag = Thread;
pre->rchild = p;
}
else p->RTag = 0;
pre = p;
InThreading(p->rchild);//递归右子树线索化
}
}
Status InOrderThreading(BiThrTree *Thrt, BiThrTree T)
{//中序遍历二叉树T,并将其线索化,Thrt指向头结点
*Thrt = (BiThrTree)malloc(sizeof(BiThrNode));
(*Thrt)->LTag = Link; (*Thrt)->RTag = Thread;//建立头结点
(*Thrt)->rchild = *Thrt; //右指针回指
if (!T) (*Thrt)->lchild = (*Thrt);//若二叉树为空,则左指针回指
else
{
(*Thrt)->lchild = T; pre = *Thrt;
InThreading(T);
pre->rchild = *Thrt; pre->RTag = Thread;//最后一个结点线索化
(*Thrt)->rchild = pre;
}
return OK;
}
Status InOrderTraverse(BiThrTree Thrt)
{
BiThrTree p;
p = Thrt->lchild;//p指向根结点
while (p != Thrt)//空树或遍历结束时,p==T
{
while (p->LTag == Link)
p = p->lchild;
printf(" %c ", p->data);
while (p->RTag == Thread && p->rchild != Thrt)
{
p = p->rchild;
printf("%c", p->data);
}
p = p->rchild;
}
return OK;
}
int main()
{
BiThrTree T,Thrt;
int cord;
do
{
printf("\n\n1.二叉链表先序创建二叉树\n");
printf("2.中序线索遍历\n");
scanf("%d", &cord);
switch (cord)
{
case 1:
{printf("输入根节点的值,#表示没有叶结点\n");
if (Create(&T))printf("创建成功\n");
}break;
case 2:{InOrderThreading(&Thrt, T);InOrderTraverse(Thrt); }break;
}
} while (cord <= 7);
return 0;
}