您的位置:首页 > 理论基础 > 数据结构算法

数据结构学习笔记 --- 二叉树

2017-02-22 07:09 603 查看
#include "ds.h"
#define CHAR // 字符型
//#define INT // 整型(二者选一)

#ifdef CHAR
typedef char TElemType;
TElemType Nil=' '; // 字符型以空格符为空
#define form "%c" // 输入输出的格式为%c
#endif

#ifdef INT
typedef int TElemType;
TElemType Nil=0; // 整型以0为空
#define form "%d" // 输入输出的格式为%d
#endif

typedef struct BiTNode
{
TElemType 	data;
BiTNode 	 *lchild, *rchild;
}BiTNode, *BiTree;

typedef 	BiTree 		QElemType;	// 设队列元素为二叉树的指针类型
typedef 	BiTree 		SElemType;  // 设栈元素为二叉树的指针类型
/****************************************************************************************/
#define ClearBiTree DestroyBiTree
typedef struct QNode{
QElemType 		data;
struct QNode 	*next;
}*QueuePtr;

struct LinkQueue{
QueuePtr 	front, rear;
};
//栈的顺序存储结构和其基本操作
#define 	STACK_INIT_SIZE 	10		// 存储空间初始分配量
#define 	STACK_INCREMENT 	2		// 存储空间分配增量

typedef struct SqStack
{
SElemType 		*base;				// 在栈构造之前和销毁之后,base的值为NULL
SElemType 		*top;				// 栈顶指针
int 			stacksize;			// 当前已分配的存储空间,以元素为单位
}SqStack;

void InitStack(SqStack &S);
void DestroyStack(SqStack &S);
void ClearStack(SqStack &S);
Status StackEmpty(SqStack S);
int StackLength(SqStack S);
Status GetTop(SqStack S, SElemType &e);
void Push(SqStack &S, SElemType e);
Status Pop(SqStack &S, SElemType &e);
void StackTraverse(SqStack S, void(* visit)(SElemType));

// 构造一个空栈S
void InitStack(SqStack &S)
{
S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S.base) exit(OVERFLOW);

S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
}

// 销毁栈S,S不再存在
void DestroyStack(SqStack &S)
{
free(S.base);
S.base = NULL;
S.top = NULL;
S.stacksize = 0;
}

// 把S置为空栈
void ClearStack(SqStack &S)
{
S.top = S.base;
}

// 若栈S为空栈,则返回TRUE,否则返回FALSE
Status StackEmpty(SqStack S)
{
if (S.top == S.base)
return TRUE;
else
return FALSE;
}

// 返回S的元素个数,即栈的长度
int StackLength(SqStack S)
{
return S.top - S.base;  // not return S.stacksize;
}

// 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
Status GetTop(SqStack S, SElemType &e)
{
if (S.top > S.base)
{
memcpy(&e, S.top - 1, sizeof(SElemType));
return OK;
}
else
{
return ERROR;
}
}

// 插入元素e为新的栈顶元素
void Push(SqStack &S, SElemType e)
{
if (S.top - S.base >= S.stacksize)
{
S.base = (SElemType*)realloc(S.base, (S.stacksize + STACK_INCREMENT) * sizeof(SElemType));
if (!S.base) exit(OVERFLOW);

S.top = S.base + S.stacksize;
S.stacksize += STACK_INCREMENT;
}

memcpy(S.top, &e, sizeof(SElemType));
S.top++;
}

// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status Pop(SqStack &S, SElemType &e)
{
if (S.top == S.base)
return ERROR;

memcpy(&e, --S.top, sizeof(SElemType));
return OK;
}

// 从栈底到栈顶依次对栈中每个元素调用函数visit()
void StackTraverse(SqStack S, void(* visit)(SElemType))
{
SElemType *p = S.base;

while(p < S.top)
{
visit(*p++);
}
printf("\n");
}

/****************************************************************************************/
void InitQueue(LinkQueue &Q);
void DestroyQueue(LinkQueue &Q);
void ClearQueue(LinkQueue &Q);
Status QueueEmpty(LinkQueue Q);
int QueueLength(LinkQueue Q);
Status GetHead(LinkQueue Q, QElemType &e);
void EnQueue(LinkQueue &Q, QElemType e);
Status DeQueue(LinkQueue &Q, QElemType &e);
void QueueTraverse(LinkQueue Q, void(*vi)(QElemType));

// 带头结点的单链队列
void InitQueue(LinkQueue &Q)
{
Q.front = (QueuePtr)malloc(sizeof(QNode));
if (!Q.front) exit(OVERFLOW);

Q.front->next = NULL;
Q.rear = Q.front;

}
void DestroyQueue(LinkQueue &Q)
{
QueuePtr q, p = Q.front;

while (p)
{
q = p->next;
free(p);
p = q;
}

Q.front = Q.rear = NULL;
}
void ClearQueue(LinkQueue &Q)
{
QueuePtr q, p = Q.front->next;

while (p)
{
q = p->next;
free(p);
p = q;
}
Q.front->next = NULL;
Q.rear = Q.front;
}
Status QueueEmpty(LinkQueue Q)
{
if (Q.front == Q.rear)
return TRUE;
else
return FALSE;
}
int QueueLength(LinkQueue Q)
{
int i = 0;
QueuePtr p = Q.front->next;

while (p)
{
i++;
p = p->next;
}

return i;
}
Status GetHead(LinkQueue Q, QElemType &e)
{
if (Q.front->next)
{
memcpy(&e, &(Q.front->next->data), sizeof(QElemType));
return OK;
}
else
{
return FALSE;
}
}
void EnQueue(LinkQueue &Q, QElemType e)
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
if (!p) exit(OVERFLOW);

p->next = NULL;
memcpy(&(p->data), &e, sizeof(QElemType));
Q.rear->next = p;
Q.rear = p;
}
Status DeQueue(LinkQueue &Q, QElemType &e)
{
QueuePtr p = Q.front, q;
if (Q.front == Q.rear)
return FALSE;

q = p->next;
memcpy(&e, &(q->data), sizeof(QElemType));
p->next = q->next;
if (Q.rear == q)
Q.rear = Q.front;
free(q);

return OK;
}
void QueueTraverse(LinkQueue Q, void(*vi)(QElemType))
{
QueuePtr p = Q.front->next;

while (p)
{
vi(p->data);
p = p->next;
}
printf("\n");
}

/****************************************************************************************/
Status InitBiTree(BiTree &T)
{
T = NULL;
return OK;
}

void DestroyBiTree(BiTree &T)
{
if (T)
{
if (T->lchild)
DestroyBiTree(T->lchild);
if (T->rchild)
DestroyBiTree(T->rchild);

free(T);
T = NULL;
}
}

// 按先序次序输入二叉树中结点的值(可为字符型或整型,在主程中定义),
// 构造二叉链表表示的二叉树T。变量Nil表示空(子)树。有改动
void CreateBiTree(BiTree &T)
{
TElemType	ch;

scanf(form, &ch);

if (ch == Nil)
T = NULL;
else
{
T = (BiTree)malloc(sizeof(BiTNode));
if (!T) exit(OVERFLOW);
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}

Status BiTreeEmpty(BiTree T)
{
if (T)
return FALSE;
else
return TRUE;
}

int BiTreeDepth(BiTree T)
{
int i, j;

if (!T)
return 0;

if (T->lchild)
i = BiTreeDepth(T->lchild);
else
i = 0;

if (T->rchild)
j = BiTreeDepth(T->rchild);
else
j = 0;

return i > j ? i+1 : j+1;
}

TElemType Root(BiTree T)
{
if (NULL == T)
return Nil;
else
return T->data;
}

TElemType Value(BiTree p)
{
return p->data;
}

void Assign(BiTree p, TElemType value)
{
p->data = value;
}

// 初始条件:二叉树T存在,e是T中某个结点
// 操作结果:若e是T的非根结点,则返回它的双亲,否则返回"空"
TElemType Parent(BiTree T, TElemType e)
{
LinkQueue 	q;
QElemType	a;

if (T)
{
InitQueue(q);
EnQueue(q, T);
while (!QueueEmpty(q))
{
DeQueue(q, a);
if (a->lchild && a->lchild->data == e || a->rchild && a->rchild->data == e)
return a->data;
else
{
if (a->lchild)
EnQueue(q, a->lchild);
if (a->rchild)
EnQueue(q, a->rchild);
}
}
}
return Nil;
}

// 返回二叉树T中指向元素值为s的结点的指针。
BiTree Point(BiTree T, TElemType s)
{
LinkQueue 	q;
QElemType	a;

if (T)
{
InitQueue(q);
EnQueue(q, T);
while (!QueueEmpty(q))
{
DeQueue(q, a);
if (a->data == s)
return a;
if (a->lchild)
EnQueue(q, a->lchild);
if (a->rchild)
EnQueue(q, a->rchild);
}
}
return NULL;
}

// 初始条件:二叉树T存在,e是T中某个结点。操作结果:返回e的左孩子。若e无左孩子,则返回"空"
TElemType LeftChild(BiTree T, TElemType e)
{
BiTree 	a;
if (T)
{
a = Point(T, e);
if (a && a->lchild)
return a->lchild->data;
}
return Nil;
}

TElemType RightChild(BiTree T, TElemType e)
{
BiTree 	a;
if (T)
{
a = Point(T, e);
if (a && a->rchild)
return a->rchild->data;
}
return Nil;
}

// 初始条件:二叉树T存在,e是T中某个结点
// 操作结果:返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空"
TElemType LeftSibling(BiTree T,TElemType e)
{
TElemType 	a;
BiTree 		p;

if (T)
{
a = Parent(T, e);
if (a != Nil)
{
p = Point(T, a);
if (p->lchild && p->rchild && p->rchild->data == e)
return p->lchild->data;
}
}
return Nil;
}

TElemType RightSibling(BiTree T,TElemType e)
{

TElemType 	a;
BiTree 		p;

if (T)
{
a = Parent(T, e);
if (a != Nil)
{
p = Point(T, a);
if (p->lchild && p->rchild && p->lchild->data == e)
return p->rchild->data;
}
}
return Nil;
}

// 初始条件:二叉树T存在,p指向T中某个结点,LR为0或1,非空二叉树c与T不相交且右子树为空
// 操作结果:根据LR为0或1,插入c为T中p所指结点的左或右子树。p所指结点的
//           原有左或右子树则成为c的右子树
Status InsertChild(BiTree p, int LR, BiTree c)
{
if (p)
{
if (LR == 0)
{
c->rchild = p->lchild;	// p所指结点的原有左或右子树则成为c的右子树
p->lchild = c;
}
else
{
c->rchild = p->rchild;
p->rchild = c;
}
return OK;
}
return ERROR;
}

// 初始条件:二叉树T存在,p指向T中某个结点,LR为0或1
// 操作结果:根据LR为0或1,删除T中p所指结点的左或右子树
Status DeleteChild(BiTree p, int LR)
{
if (p)
{
if (LR == 0)
{
ClearBiTree(p->lchild);
}
else
{
ClearBiTree(p->rchild);
}
return OK;
}
return ERROR;
}

// 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。算法6.3,有改动
// 中序遍历二叉树T的非递归算法(利用栈),对每个数据元素调用函数Visit
void InOrderTraverse1(BiTree T, void(*Visit)(TElemType))
{
SqStack 	S;

InitStack(S);
while (T || !StackEmpty(S))
{
if (T)
{
Push(S, T);
T = T->lchild;
}
else
{
Pop(S, T);
Visit(T->data);
T = T->rchild;
}
}
printf("\n");
}

// 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。算法6.2,有改动
// 中序遍历二叉树T的非递归算法(利用栈),对每个数据元素调用函数Visit
void InOrderTraverse2(BiTree T,void(*Visit)(TElemType))
{
SqStack	S;
BiTree 	p;
InitStack(S);
Push(S, T);
while (!StackEmpty(S))
{
while (GetTop(S, p) && p)
Push(S, p->lchild);
Pop(S, p); // 空指针退栈
if (!StackEmpty(S))
{
Pop(S, p);
Visit(p->data);
Push(S, p->rchild);
}
}
printf("\n");
}

// 初始条件:二叉树T存在,Visit是对结点操作的应用函数
// 操作结果:后序递归遍历T,对每个结点调用函数Visit一次且仅一次
void PostOrderTraverse(BiTree T,void(*Visit)(TElemType))
{
if(T) // T不空
{
PostOrderTraverse(T->lchild,Visit); // 先后序遍历左子树
PostOrderTraverse(T->rchild,Visit); // 再后序遍历右子树
Visit(T->data); // 最后访问根结点
}
}

// 初始条件:二叉树T存在,Visit是对结点操作的应用函数
// 操作结果:先序递归遍历T,对每个结点调用函数Visit一次且仅一次
void PreOrderTraverse(BiTree T,void(*Visit)(TElemType))
{
if(T) // T不空
{
Visit(T->data); // 先访问根结点
PreOrderTraverse(T->lchild,Visit); // 再先序遍历左子树
PreOrderTraverse(T->rchild,Visit); // 最后先序遍历右子树

}
}

// 初始条件:二叉树T存在,Visit是对结点操作的应用函数
// 操作结果:层序递归遍历T(利用队列),对每个结点调用函数Visit一次且仅一次
void LevelOrderTraverse(BiTree T,void(*Visit)(TElemType))
{
LinkQueue q;
QElemType a;
if(T)
{
InitQueue(q); // 初始化队列q
EnQueue(q,T); // 根指针入队
while(!QueueEmpty(q)) // 队列不空
{
DeQueue(q,a); // 出队元素(指针),赋给a
Visit(a->data); // 访问a所指结点
if(a->lchild!=NULL) // a有左孩子
EnQueue(q,a->lchild); // 入队a的左孩子
if(a->rchild!=NULL) // a有右孩子
EnQueue(q,a->rchild); // 入队a的右孩子
}
printf("\n");
}
}

void visitT(TElemType e)
{
printf(form" ", e);
}

int main()
{
int i;
BiTree T,p,c;
TElemType e1,e2;
InitBiTree(T);
printf("构造空二叉树后,树空否?%d(1:是 0:否)树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
e1=Root(T);
if(e1!=Nil)
printf("二叉树的根为: "form"\n",e1);
else
printf("树空,无根\n");
#ifdef CHAR
printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
CreateBiTree(T);
printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
e1=Root(T);
if(e1!=Nil)
printf("二叉树的根为: "form"\n",e1);
else
printf("树空,无根\n");
printf("中序递归遍历二叉树:\n");
InOrderTraverse1(T,visitT);
printf("\n后序递归遍历二叉树:\n");
PostOrderTraverse(T,visitT);
printf("\n请输入一个结点的值: ");
scanf("%*c"form,&e1);
p=Point(T,e1); // p为e1的指针
printf("结点的值为"form"\n",Value(p));
printf("欲改变此结点的值,请输入新值: ");
scanf("%*c"form"%*c",&e2); // 后一个%*c吃掉回车符,为调用CreateBiTree()做准备
Assign(p,e2);
printf("层序遍历二叉树:\n");
LevelOrderTraverse(T,visitT);
e1=Parent(T,e2);
if(e1!=Nil)
printf("%c的双亲是"form"\n",e2,e1);
else
printf(form"没有双亲\n",e2);
e1=LeftChild(T,e2);
if(e1!=Nil)
printf(form"的左孩子是"form"\n",e2,e1);
else
printf(form"没有左孩子\n",e2);
e1=RightChild(T,e2);
if(e1!=Nil)
printf(form"的右孩子是"form"\n",e2,e1);
else
printf(form"没有右孩子\n",e2);
e1=LeftSibling(T,e2);
if(e1!=Nil)
printf(form"的左兄弟是"form"\n",e2,e1);
else
printf(form"没有左兄弟\n",e2);
e1=RightSibling(T,e2);
if(e1!=Nil)
printf(form"的右兄弟是"form"\n",e2,e1);
else
printf(form"没有右兄弟\n",e2);
InitBiTree(c);
printf("构造一个右子树为空的二叉树c:\n");
#ifdef CHAR
printf("请先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");
#endif
#ifdef INT
printf("请先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");
#endif
CreateBiTree(c);
printf("先序递归遍历二叉树c:\n");
PreOrderTraverse(c,visitT);
printf("\n层序遍历二叉树c:\n");
LevelOrderTraverse(c,visitT);
printf("树c插到树T中,请输入树T中树c的双亲结点 c为左(0)或右(1)子树: ");
scanf("%*c"form"%d",&e1,&i);
p=Point(T,e1); // p是T中树c的双亲结点指针
InsertChild(p,i,c);
printf("先序递归遍历二叉树:\n");
PreOrderTraverse(T,visitT);
printf("\n中序非递归遍历二叉树:\n");
InOrderTraverse1(T,visitT);
printf("删除子树,请输入待删除子树的双亲结点  左(0)或右(1)子树: ");
scanf("%*c"form"%d",&e1,&i);
p=Point(T,e1);
DeleteChild(p,i);
printf("先序递归遍历二叉树:\n");
PreOrderTraverse(T,visitT);
printf("\n中序非递归遍历二叉树(另一种方法):\n");
InOrderTraverse2(T,visitT);
DestroyBiTree(T);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: