《数据结构》上机实验(第七章) —树与二叉树Ⅳ

在这里插入图片描述

1. 求以孩子兄弟表示法存储的森林的叶子结点数。

  • 算法思想:当森林(树)以孩子兄弟表示法存储时,若结点没有孩子,则它必是叶子,当森林(树)转化为以孩子兄弟表示法存储的二叉树时,如果某个结点的左孩子为NULL,则该结点就是原森林(树)的叶子结点。
int Leaves(CSTree t)
{
	static int count = 0;
	if (t == NULL) return 0;
	else
	{
		if (t->firstchild == NULL)
		{
			printf("%c ", t->data);
			count++;
		}
		Leaves(t->firstchild);
		Leaves(t->nextsibling);
	}
	return count;
}

运行结果

在这里插入图片描述
在这里插入图片描述

2. 以孩子兄弟链表为存储结构,求树的深度。

  • 算法思想:采用递归算法,若树为空,高度为零;否则,高度为第一子女树高度加1和兄弟子树高度的大者。
  • 其非递归算法使用队列,逐层遍历取得树的高度。
int Height(CSTree t)
{
	int h1, h2;
	if (t == NULL) return 0;
	else
	{
		h1 = Height(t->firstchild);
		h2 = Height(t->nextsibling);
		if (h1 + 1 > h2) return h1 + 1;
		else return h2;
	}
}

运行结果

在这里插入图片描述在这里插入图片描述

3. 已知一棵树的层次序列及每个结点的度,构造此树的孩子—兄弟链表。

  • 本题与树的层次序列有关。可设立一个辅助数组pointer[ ]存储新建树的各结点的地址,再根据层次序列与每个结点的度,逐个链接结点。
#define MaxNode 15
void CreateCSTree(CSTree& t, ElemType e[], int degree[], int n)
{
	//根据树结点的层次序列e[]和各结点的度degree[]构造树的孩子-兄弟链表,参数n是树的结点个数
	CSNode* pointer = new CSNode[MaxNode];
	int i, j, d, k = 0;
	for (i = 0; i < n; i++) //初始化
	{
		pointer[i]->data = e[i];
		pointer[i]->firstchild = pointer[i]->nextsibling = NULL;
	}
	for (i = 0; i < n; i++)
	{
		d = degree[i]; //结点i的度数
		if (d != 0)
		{
			k++;
			pointer[i]->firstchild = pointer[k]; //建立i与子女k间的连接
			for (j = 2; j <= d; j++)
			{
				k++;
				pointer[k - 1]->nextsibling = pointer[k];
			}
		}
	}
	T = pointer[0];
	delete[] pointer;
}

4. 判断给定的二叉树是否是二叉排序树。

bool isBST(BiTree t) //判断给定的二叉树是否是二叉排序树
{
    if (t != NULL) //非空树
    {
        if (t->lchild != NULL)
        {
            if (t->lchild->data > t->data) return false; //左子树结点的关键字>根结点的关键字,返回false
            else if (t->rchild != NULL)
            {
                if (t->rchild->data < t->data) return false; //右子树结点的关键字<根结点的关键字,返回false
            }
        }    
        isBST(t->lchild);
        isBST(t->rchild);
    }
    else return true; //空树或者二叉排序树遍历结束,返回true
}

运行结果

在这里插入图片描述

5. 求出指定结点在给定二叉排序树中的层次。

int Level(BiTree t, ElemType key)
{
    static int count = 1;
    if (t != NULL)
    {
        if (t->data == key) return count;
        else if (t->data > key)
        {
            Level(t->lchild, key);
            count++;
        }
        else
        {
            Level(t->rchild, key);
            count++;
        }
    }
    return count;
}

运行结果

在这里插入图片描述

6. 判断二叉树是否是平衡二叉树。

void isAVL(BiTree t, int& balance, int& h) //判断给定的二叉树是否是平衡排序树
{
    int bl = 0, br = 0, hl = 0, hr = 0; //左、右子树的平衡标记的高度
    if (t == NULL) //空树,高度为0
    {
        h = 0;
        balance = 1;
    }
    else if (t->lchild == NULL && t->rchild == NULL) //仅有根结点,则高度为1
    {
        h = 1;
        balance = 1;
    }
    else
    {
        isAVL(t->lchild, bl, hl); //递归判断左子树
        isAVL(t->rchild, br, hr); //递归判断右子树
        h = (hl > hr ? hl : hr) + 1;
        if (abs(hl - hr) < 2) balance = bl && br; //若子树高度差的绝对值<2,则看左、右子树是否都平衡
        else balance = 0;
    }
}

运行结果

在这里插入图片描述

7. 求出给定二叉排序树中最小和最大的关键字。

void Min_MaxKey(BiTree t,ElemType &min,ElemType &max)
{
    BiTNode* p, * q;
    if (t->lchild == NULL && t->rchild == NULL) min=t->data;
    else
    {
        p = q = t;
        while (p->rchild != NULL) p = p->rchild; //最右下结点即为关键字最大的结点
        max = p->data;
        while (q->lchild != NULL) q = q->lchild; //最左下结点即为关键字最小的结点
        min = q->data;
    }
}

运行结果

在这里插入图片描述

8. 从大到小输出二叉排序树中所有值不小于k的关键字。

void OutPut(BiTree t, ElemType key)
{
	if (t == NULL) return;
	else
	{
		if (t->rchild != NULL) OutPut(t->rchild, key); //递归输出右子树结点
		if (t->data >= key) printf("%d ", t->data); //只输出≥k的结点值
		if (t->lchild != NULL) OutPut(t->lchild, key); //递归输出左子树结点
	}
}

运行结果

在这里插入图片描述

9. 编写一个递归算法,在一棵有m个结点的、随机建立起来的二叉排序树上查找第k(1≤k≤m)小的元素,并返回指向该结点的指针。要求算法的平均时间复杂度为 O ( l o g 2 n O(log_2^n O(log2n)。二叉排序树的每个结点中除data,lchild,rchild等数据成员外,增加一个 count成员,保存以该结点为根的子树上的结点个数。

  • 算法思想:设二叉排序树的根结点为*t,根据结点存储的信息,有以下几种情况:
  • t->lchild为空时,情况如下:
    1)若t->rchild非空且k==1,则*t即为第k小的元素,查找成功。
    2)若t->rchild非空且k!=1,则第k小的元素必在*t的右子树。
  • 若t->lchild非空时,情况如下:
    1)t->lchild->count==k-1,*t即为第k小的元素,查找成功。
    2)t->lchild->count>k-1,第k小的元素必在*t的左子树,继续到*t的左子树中查找。
    3)t->lchild->count<k-1,第k小的元素必在右子树,继续搜索右子树,寻找第k(t->lchild->count+1)小的元素。
    对左右子树的搜索采用相同的规则。
BiTNode* Search_Small(BiTNode* t, int k)
{
	if (k<1 || k>t->count) return NULL;
	if (t->lchild == NULL) //t->lchild为空
	{
		if (k == 1) return t; //k=1,根结点为第1小的元素,查找成功
		else return Search_Small(t, k - 1); //k≠1
	}
	else //t->lchild非空时
	{
		if (t->lchild->count == k - 1) return t; //左子树中刚好有k-1个节点,根结点为第k小的元素,查找成功
		if (t->lchild->count > k - 1) return Search_Small(t->lchild, k); //第k小的元素必在左子树
		if (t->lchild->count < k - 1) return Search_Small(t->rchild, k - (t->lchild->count + 1)); //第k小的元素必在右子树
	}
}

10. 假设二叉排序树bt中所有的关键字是由整数构成的,为了查找某关键字k,会得到一个查找序列。判断一个序列(存放在a数组中)是否是从bt中搜索关键字k的序列。

  • 算法思想:设查找序列a中有n个关键字,如果查找成功,a[n-1]应等于k。用i扫描a数组(初值为0),p用于在二叉排序树bt中查找(p的初值指向根结点),每查找一层,比较该层的结点关键字pー>key是否等于a[i],若不相等,表示a不是bt中查找关键字k的序列,返回false;否则继续查找下去。若一直未找到关键字k,则p最后必为NULL,表示a不是查找序列,返回false;否则表示在bt中查找到k,p指向该结点,表示a是查找序列,返回true。
bool Findseq(BSTNode* bt, int k, int a[], int n)
{
	BSTNode* p = bt;
	int i = 0;
	if (a[n - 1] != k) return false; //未找到k,返回false
	while (i < n && p != NULL)
	{
		if (p.key != a[i]) return false; //若不等,表示a不是k的查找序列
		if (k < p.key) p = p.lchild; //在左子树中查找
		else if (k > p.key) p = p.rchild; //在右子树中查找
		i++; //查找序列指向下一个关键字
	}
	if (p != NULL) return true; //找到了k,返回true
	else return false; //未找到k,返回false
}

运行结果

在这里插入图片描述

11. 对于二叉排序树bt设计一个算法,输出在该树中查找某个关键字k所经过的路径。

  • 算法思想:设计的算法为SearchPath(BSTNode *bt, KeyType k, KeyType path[ ],intd),它输出二叉排序树bt中査找关键字k的查找路径。使用path数组存储经过的结点,d表示path中最后关键字的下标,初始值为-1。当找到所要找的结点时,输出path数组中的元素值,从而以根结点到当前结点输出路径。
void SearchPath(BSTNode* bt, ElemType k, ElemType path[], int d)
//d表示path中最后关键字的下标,初始值为-1
{
	if (bt == NULL) return;
	else if (k == bt->data)
	{
		d++;
		path[d] = bt->data; //添加到路径中
		for (int i = 0; i <= d; i++) printf("%2d ", path[i]);
		printf("\n");
	}
	else
	{
		d++;
		path[d] = bt->data; //添加到路径中
		if (k < bt->data) SearchPath(bt->lchild, k, path, d); //在左子树中递归查找
		else SearchPath(bt->rchild, k, path, d); //在右子树中递归查找
	}
}

运行结果

在这里插入图片描述

12. 假设二叉树采用二叉链存储结构,设计一个算法输出值为x的结点的所有祖先。

  • 根据二叉树中祖先的定义可知,若结点p的左孩子或右孩子是结点q,则结点p是结点q的祖先;若结点p的左孩子或右孩子是q结点的祖先;则结点也是结点q的祖先。
  • 设f(b,x)表示结点b是否为值是x的结点的祖先,若结点b是值为的结点的祖先f(b,x),返回true;否则f(b,x)返回false。当f(b,x)为true时,输出结点b的值。求值为x的结点的所有祖先的递归模型f(b,x)如下:
    { f ( b , x ) = f a l s e            若 b = N U L L f ( b , x ) = t r u e , 并 输 出 b − > d a t a            若 结 点 b 的 左 孩 子 或 右 孩 子 的 d a t a 域 为 x f ( b , x ) = t r u e , 并 输 出 b − > d a t a            若 f ( b − > l c h i l d , x ) 为 t r u e 或 f ( b − > r c h i l d , x ) 为 t r u e f ( b , x ) = f a l s e            其 他 情 况 \begin{cases} f(b, x)=false\;\;\;\;\;若b=NULL\\ f(b,x)=true,并输出b->data\;\;\;\;\;若结点b的左孩子或右孩子的data域为x\\ f(b,x)=true,并输出b->data\;\;\;\;\;若f(b->lchild,x)为true或f(b-> rchild,x)为true\\ f(b, x)= false\;\;\;\;\;其他情况 \end{cases} f(b,x)=falseb=NULLf(b,x)=trueb>databdataxf(b,x)=trueb>dataf(b>lchild,x)truef(b>rchild,x)truef(b,x)=false
bool Ancestor(BiTNode* t, ElemType x)
{
    if (t == NULL) return false;
    else if (t->lchild != NULL && t->lchild->data == x || t->rchild != NULL && t->rchild->data == x)
    {
        printf("%c ", t->data);
        return true;
    }
    else if (Ancestor(t->lchild, x) || Ancestor(t->rchild, x))
    {
        printf("%c ", t->data);
        return true;
    }
    else return false;
}

运行结果

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值