zoukankan      html  css  js  c++  java
  • 基于数组的完全二叉树

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

    完全二叉树特征:

    • 层序存储位置(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("树空,无根
    ");
    	
    }
    
  • 相关阅读:
    N in 1 & 多重引导光盘制作
    可启动 ISO 合并、Windows 安装光盘合集
    VS 2005 VC++ 文件类型
    Windows 无人值守安装应答文件详解
    30种下载Youtube视频的方法
    解释YOUTUBE FLV 地址
    Windows下进程通信方式[转]
    进程通讯 DELPHI的类实现
    c#.net常用函数列表
    Javascript, How to make a Dress Up Game (Drag and Drop)
  • 原文地址:https://www.cnblogs.com/neen/p/13651726.html
Copyright © 2011-2022 走看看