现在的位置: 首页 > 综合 > 正文

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

2013年10月02日 ⁄ 综合 ⁄ 共 10083字 ⁄ 字号 评论关闭
#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);
}

抱歉!评论已关闭.