基于数组的完全二叉树

以下实现的是一个基于数组存储的完全二叉树

完全二叉树特征:

  • 层序存储位置(k, p)与数组位置(i)之间的关系:i = 2^(p-1) + (q -1)
  • 数组中,结点(p)与左子树(i)的位置关系:i = 2*p + 1
  • 数组中,结点(p)与右子树(i)的位置关系:i = 2*p + 2
  • 数组中,子结点(p)与父亲结点(i)的位置关系:i = (p + 1) / 2 - 1
  • 深度 k 与 结点数 n 之间的关系: n <= (2^k - 1)
// BinaryTree
// BinaryTree
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// 定义两个常量
#define MAXSIZE 100								// 存储空间初始分配量
#define MAX_TREE_SIZE 100						// 二叉树最大结点数
#define TRUE 1
#define FALSE 0
#define STATUS_OK 1
#define STATUS_FAILED 0

typedef int TElemType;
typedef TElemType BinaryTree[MAX_TREE_SIZE];		

// 定义二叉树的数据结构
typedef struct
{
	int level; // 结点的层
	int order; // 本层序号
}Position;

TElemType Nil = 0; // 定义TElemType的空类型

// 构造空二叉树
void InitBiTree(BinaryTree T)
{
	for (int i = 0; i < MAX_TREE_SIZE; i++)
	{
		T[i] = Nil;
	}
}
#define ClearBiTree InitBiTree // 在顺序存储结构中,两函数完全一样

int BiTreeEmpty(BinaryTree T)
{
	if (T[0] == Nil)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

void visit(TElemType e)
{
	printf(" %d ", e);
}

int Root(BinaryTree T, TElemType* e)
{
	if (!BiTreeEmpty(T)) { // 不空,e赋值根结点
		*e = T[0];
		return STATUS_OK;
	} else { // 空,返回错误状态
		return STATUS_FAILED;
	}
}

// 深度计算
// 利用了性质:深度为k的二叉树的结点数: n <= (2^k - 1)
int BiTreeDepth(BinaryTree T)					
{
	int i, j = -1;
	for (i = MAX_TREE_SIZE - 1; i >= 0; i--)	// 找到最后一个结点
	{
		if (T[i] != Nil)						// 不为Nil的结点	
			break;
	}
	i++; // 结点数n + 1;
	do {
		j++;
	} while (i >= powl(2, j));					// 计算2的j次幂
	printf("计算深度时,对比i(n+1):%d, j(2^k):%d
", i, j);
	return j;
}

// 以层序创建基于数组的完全二叉树(10个结点), 此时双亲结点i与左右子树的索引关系:2*i+1, 2*1+2
void CreateBiTree(BinaryTree T)
{
	int i = 0;
	printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:
", MAX_TREE_SIZE);
	while (i < 10)								// 层序遍历创建一个10个结点的二叉树
	{
		T[i] = i + 1;							// T[0] - T[9]: 1 2 3 4 5 6 7 8 9 10
		if (i != 0 && T[(i + 1) / 2 - 1] == Nil 
			&& T[i] != Nil)						// 此结点(不空)无双亲且不是根【目前没见过此种情况的出现】
		{
			printf("出现无双亲的非根结点%d
", T[i]);
			exit(0);
		}
		i++;
	}
	while (i < MAX_TREE_SIZE)
	{
		T[i] = Nil;
		i++;
	}
}

void TraverseArray(BinaryTree T)
{
	for (int i = MAX_TREE_SIZE - 1; i >= 0; i--)
	{
		visit(T[i]);
	}
}

void LevelOrderTraverse(BinaryTree T) 
{
	int i = MAX_TREE_SIZE - 1, j;
	while (T[i] == Nil)
	{
		i--;									// 找到最后一个非空结点的序号
	}
		
	for (j = 0; j <= i; j++)					// 从根结点起,按层序遍历二叉树
	{
		if (T[j] != Nil)
			visit(T[j]);						// 只遍历非空的结点
	}
	printf("
");
}

void PreTraverse(BinaryTree T, int index)
{
	visit(T[index]);							// 访问根结点
	if (T[2 * index + 1] != Nil)				// 左子树不空
		PreTraverse(T, 2 * index + 1);
	if (T[2 * index + 2] != Nil)				// 右子树不空 
		PreTraverse(T, 2 * index + 2);
}

void PreOrderTraverse(BinaryTree T)
{
	if (!BiTreeEmpty(T)) /* 树不空 */
		PreTraverse(T, 0);
	printf("
");
}

void InTraverse(BinaryTree T, int index)
{
	if (T[2 * index + 1] != Nil) /* 左子树不空 */
		InTraverse(T, 2 * index + 1);
	visit(T[index]);
	if (T[2 * index + 2] != Nil) /* 右子树不空 */
		InTraverse(T, 2 * index + 2);
}

void InOrderTraverse(BinaryTree T)
{
	if (!BiTreeEmpty(T)) /* 树不空 */
		InTraverse(T, 0);
	printf("
");
}

void PostTraverse(BinaryTree T, int index)
{
	if (T[2 * index + 1] != Nil) /* 左子树不空 */
		PostTraverse(T, 2 * index + 1);
	if (T[2 * index + 2] != Nil) /* 右子树不空 */
		PostTraverse(T, 2 * index + 2);
	visit(T[index]);
}

void PostOrderTraverse(BinaryTree T)
{
	if (!BiTreeEmpty(T)) /* 树不空 */
		PostTraverse(T, 0);
	printf("
");
}
// [(2^(k-1)-1) + (q-1)]
int Value(BinaryTree T, Position p)
{
	return T[(int)powl(2, p.level - 1) + p.order - 2];
}

void Assign(BinaryTree T, Position p, TElemType value)
{
	int i = (int)powl(2, p.level - 1) + p.order - 2; // 将层号、本层序号转为矩阵的序号 
	if (value != Nil && T[(i + 1) / 2 - 1] == Nil) /* 给叶子赋非空值但双亲为空 */
		return;
	else if (value == Nil && (T[i * 2 + 1] != Nil || T[i * 2 + 2] != Nil)) /*  给双亲赋空值但有叶子(不空) */
		return;
	T[i] = value;
}

TElemType Parent(BinaryTree T, TElemType e)
{
	int i;
	if (T[0] == Nil) /* 空树 */
		return Nil;
	for (i = 1; i <= MAX_TREE_SIZE - 1; i++)
		if (T[i] == e) /* 找到e */
			return T[(i + 1) / 2 - 1];
	return Nil; /* 没找到e */
}

/* 初始条件: 二叉树T存在,e是T中某个结点 */
/* 操作结果: 返回e的左孩子。若e无左孩子,则返回"空" */
TElemType LeftChild(BinaryTree T, TElemType e)
{
	int i;
	if (T[0] == Nil) /* 空树 */
		return Nil;
	for (i = 0; i <= MAX_TREE_SIZE - 1; i++)
		if (T[i] == e) /* 找到e */
			return T[i * 2 + 1];
	return Nil; /* 没找到e */
}

/* 初始条件: 二叉树T存在,e是T中某个结点 */
/* 操作结果: 返回e的右孩子。若e无右孩子,则返回"空" */
TElemType RightChild(BinaryTree T, TElemType e)
{
	int i;
	if (T[0] == Nil) /* 空树 */
		return Nil;
	for (i = 0; i <= MAX_TREE_SIZE - 1; i++)
		if (T[i] == e) /* 找到e */
			return T[i * 2 + 2];
	return Nil; /* 没找到e */
}

/* 初始条件: 二叉树T存在,e是T中某个结点 */
/* 操作结果: 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空" */
TElemType LeftSibling(BinaryTree T, TElemType e)
{
	int i;
	if (T[0] == Nil) /* 空树 */
		return Nil;
	for (i = 1; i <= MAX_TREE_SIZE - 1; i++)
		if (T[i] == e && i % 2 == 0) /* 找到e且其序号为偶数(是右孩子) */
			return T[i - 1];
	return Nil; /* 没找到e */
}

/* 初始条件: 二叉树T存在,e是T中某个结点 */
/* 操作结果: 返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回"空" */
TElemType RightSibling(BinaryTree T, TElemType e)
{
	int i;
	if (T[0] == Nil) /* 空树 */
		return Nil;
	for (i = 1; i <= MAX_TREE_SIZE - 1; i++)
		if (T[i] == e && i % 2) /* 找到e且其序号为奇数(是左孩子) */
			return T[i + 1];
	return Nil; /* 没找到e */
}

int main()
{
	Position p;
	TElemType e;
	BinaryTree T;
	int result;
	InitBiTree(T);
	CreateBiTree(T);
	printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d
", BiTreeEmpty(T), BiTreeDepth(T));

	Root(T, &e);
	printf("二叉树的根为:%d
", e);
		
	printf("层序遍历二叉树:
");
	LevelOrderTraverse(T);
	printf("前序遍历二叉树:
");
	PreOrderTraverse(T);
	printf("中序遍历二叉树:
");
	InOrderTraverse(T);
	printf("后序遍历二叉树:
");
	PostOrderTraverse(T);

	printf("修改结点的层号3本层序号2。");
	p.level = 3;
	p.order = 2;
	e = Value(T, p);
	printf("待修改结点的原值为%d请输入新值:50 ", e);
	e = 50;
	Assign(T, p, e);

	printf("前序遍历二叉树:
");
	PreOrderTraverse(T);
	printf("结点%d的双亲为%d,", e, Parent(T, e));
	printf("左右孩子分别为%d,%d,", LeftChild(T, e), RightChild(T, e));
	printf("左右兄弟分别为%d,%d
", LeftSibling(T, e), RightSibling(T, e));


	ClearBiTree(T);
	printf("清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d
", BiTreeEmpty(T), BiTreeDepth(T));
	TraverseArray(T);
	result = Root(T, &e);
	if (result == STATUS_OK)
		printf("二叉树的根为:%d
", e);
	else
		printf("树空,无根
");
	
}
原文地址:https://www.cnblogs.com/neen/p/13651726.html