【数据结构与算法】树和二叉树(头歌)

树和二叉树

第1关:二叉树的基本操作

任务描述

测试说明

代码

第2关:输出二叉树后序遍历的逆序

任务描述

测试说明 

代码 

 第3关:按中序输出二叉树中的分支结点

任务描述

测试说明

 代码

第4关:前序输出二叉树节点值与层次值

任务描述

测试说明

代码 

 第5关:求二叉树中结点个数

任务描述

测试说明

 代码

第6关:求二叉树叶子结点数

任务描述

测试说明

代码 

 第7关:求二叉树的深度

任务描述

测试说明

代码 

第8关:二叉树交换左右子树

任务描述

测试说明

代码 

第9关:按中序遍历次序输出二叉树中度为1的结点

任务描述

测试说明

 代码

第1关:二叉树的基本操作

任务描述

题目描述: 设计二叉树,能够对二叉树进行先序、中序、后序和层序遍历,遍历的操作为输出结点的值,设计主函数,输入一棵二叉树,按先序、中序、后序、层序的遍历顺序输出结点的值。二叉树的结点数不超过20。

测试说明

输入描述:输入数据只有一组, 二叉树的结点均为一个数字, 数据为 0 代表当前结点为空。输入结点的值按照二叉树的先序遍历顺序, 比如输入:1 2 4 0 0 5 0 0 3 0 6 0 0, 0 表示空,输入的数字之间由空格分隔。

  1. 1
  2. / \
  3. 2 3
  4. / \ \
  5. 4 5 6

输出描述:输出先序、中序、后序和层序遍历二叉树得到的序列,各占一行,同一行的数字之间由空格分隔。

输入样例:

1 2 4 0 0 5 0 0 3 0 6 0 0

输出样例:

1 2 4 5 3 6

4 2 5 1 3 6

4 5 2 6 3 1

1 2 3 4 5 6

代码

#include <stdio.h>
#include <stdlib.h>

struct BiNode {
    int data;
    struct BiNode *lchild, *rchild;
};

struct BiTree {
    struct BiNode *root;
};

void PreOrder(struct BiNode *bt) {
	//TODO:前序遍历递归算法
	//=========begin========
    if (bt == NULL)
    {
    	return;
	}
	else
	{
		printf("%d ", bt->data);
		PreOrder(bt->lchild);
		PreOrder(bt->rchild);
	}
	//==========end==========
}

void InOrder(struct BiNode *bt) {
	//TODO:中序遍历递归算法
	//=========begin========
    if (bt == NULL)
    {
    	return;
	}
	else
	{
		InOrder(bt->lchild);
		printf("%d ", bt->data);
		InOrder(bt->rchild);
	}    
	//==========end==========
}

void PostOrder(struct BiNode *bt) {
	//TODO:后序遍历递归算法
	//=========begin========
    if (bt == NULL)
    {
    	return;
	}
	else
	{
		PostOrder(bt->lchild);
		PostOrder(bt->rchild);
		printf("%d ", bt->data);
	}    
	//==========end==========
}

void LevelOrder(struct BiNode *root) {
	//TODO:层次序遍历
	//=========begin========
    int front = -1, rear = -1;
    struct BiNode *q;
    struct BiNode *Q[30];
    
    if (root == NULL)
    {
    	return;
	}
    
	Q[++rear] = root;
	
	while (front != rear)
	{
		q = Q[++front];
		printf("%d ", q->data);
		
		if (q->lchild != NULL)
		{
			Q[++rear] = q->lchild;
		}
		
		if (q->rchild != NULL)
		{
			Q[++rear] = q->rchild;
		}
	}
	//==========end==========
}

struct BiNode *Create(struct BiNode *bt) {
	//TODO:前序建立二叉树
	//=========begin========
    int num;
    
    scanf(" %d", &num);
    
    if (num == 0)
    {
    	bt = NULL;
	}
	else
	{
		bt = (struct BiNode*)malloc(sizeof(struct BiNode));
		bt->data = num;
		bt->lchild = Create(bt->lchild);
		bt->rchild = Create(bt->rchild); 		
	}
    
    return bt;
	//==========end==========
}

void Release(struct BiNode *bt) {
	//TODO:销毁二叉树
	//=========begin========
    if (bt != NULL)
    {
    	Release(bt->lchild);
    	Release(bt->rchild);
    	free(bt);
	}
	//==========end==========
}

int main() {
    struct BiTree b;
    b.root = Create(b.root);
    PreOrder(b.root);
    printf("\n");
    InOrder(b.root);
    printf("\n");
    PostOrder(b.root);
    printf("\n");
    LevelOrder(b.root);
    Release(b.root);
    return 0;
}

第2关:输出二叉树后序遍历的逆序

任务描述

题目描述: 采用先序法建立一棵二叉树,设计输出二叉树后序遍历的逆序,二叉树的数据域类型为字符型,扩展二叉树的叶子结点用‘#’表示,要求可以输出多棵二叉树的后序遍历逆序,当二叉树为空时程序结束。

测试说明 

输入描述:循环输入多棵扩展二叉树的先序遍历序列,每棵树占一行,以回车结束,每棵二叉树中结点之间以空格隔开

输出描述:输出各二叉树后序遍历逆序,每次输出后面都换行,当二叉树为空时,输出“NULL”,程序结束。

输入样例:

A B # # C D # E # F # # G H # I K # # # #

A B D H # # I # # E J # # K # # C F L # # M # # G N # # O # #

#

输出样例:

A C G H I K D E F B

A C G O N F M L B E K J D I H

NULL

代码 

#include <stdio.h>
#include <stdlib.h>

struct BiNode {
    char data;
    struct BiNode *lchild, *rchild;
};

struct BiTree {
    struct BiNode *root;
};

struct Stack{
	char data[100];
	int top;
};

void Init(struct Stack *s)
{
	s->top = -1;
}

void Push(struct Stack *s, char x)
{
	s->data[++s->top] = x;
}

char Pop(struct Stack *s)
{
	return s->data[s->top--];
}

void Print(struct Stack *s)
{
	while (s->top != -1)
	{
		printf("%c ", Pop(s));
	}
}

struct BiNode *Create(struct BiNode *bt) {
    char ch;
    scanf("%c ", &ch);
    if (ch == '#')
        bt = NULL;
    else {
        bt = (struct BiNode *)malloc(sizeof(struct BiNode));
        bt->data = ch;
        bt->lchild = Create(bt->lchild);
        bt->rchild = Create(bt->rchild);
    }
    return bt;
}

void RePreOrder(struct BiNode *bt, struct Stack *s) {
	//ToDo 递归输出二叉树后序遍历的逆序
	//========begin======
    if (bt == NULL)
    {
    	return;
	}
    else
	{
		RePreOrder(bt->lchild, s);
		RePreOrder(bt->rchild, s);
		Push(s, bt->data);
	}
	//=========end=======
}

int Empty(struct BiTree *tree) {
	//ToDo 判断是否为空
	//========begin======
   	if (tree->root == NULL)
   	{
   		return 1;
	}
	else
	{
		return 0;
	}
	//=========end=======
}

int main() {
    while (1) {
        struct BiTree A;
        //ToDo 设计主函数 以满足题意
		//========begin======
       	struct Stack s;
	    
		A.root = Create(A.root);
        Init(&s);
        
        if (Empty(&A))
        {
        	printf("NULL");
        	break;
		}
        
        RePreOrder(A.root, &s);
        Print(&s);
		printf("\n");
		//=========end=======
    }
    
    return 0;
}

 第3关:按中序输出二叉树中的分支结点

任务描述

题目描述: 二叉树的结点数据域是字符型,空结点用‘#’表示,按前序遍历建立二叉树,按中序输出二叉树中所有的分支结点,以空格隔开。

测试说明

输入描述: 输入二叉树的扩展二叉树的前序遍历序列。

输出描述: 按中序输出二叉树中所有的分支结点,以空格隔开,最后一个结点后面有空格,占一行。

输入样例:

AB#C##D##

输出样例:

B A

 代码

#include <stdio.h>
#include <stdlib.h>

struct BiNode {
    char data;
    struct BiNode *lchild, *rchild;
};

struct BiTree {
    struct BiNode *root;
};

struct BiNode *Create(struct BiNode *bt) {
    char ch;
    scanf(" %c", &ch);
    if (ch == '#')
        return NULL;
    else {
        bt = (struct BiNode *)malloc(sizeof(struct BiNode));
        bt->data = ch;
        bt->lchild = Create(bt->lchild);
        bt->rchild = Create(bt->rchild);
    }
    return bt;
}

void InOrder(struct BiNode *bt) {
	//ToDo 中序输出分支节点
	//========begin=======
    if (bt == NULL)
    {
    	return;
	}
	else
	{
		InOrder(bt->lchild);
		
		if (bt->lchild != NULL || bt->rchild != NULL)
		{
			printf("%c ", bt->data);
		}
		
		InOrder(bt->rchild);
	}
	//=========end========
}

int Empty(struct BiTree *tree) {
    if (tree->root == NULL)
        return 1;
    else
        return 0;
}

int main() {
    struct BiTree btree;
	//ToDo 设计主函数 以满足题目需求
	//========begin=======
    btree.root = Create(btree.root);
    
    InOrder(btree.root);
	//=========end========
    return 0;
}

第4关:前序输出二叉树节点值与层次值

任务描述

本关任务:设二叉树采用二叉链表存放,该结点结构为[lchild,data,level,rchild], 将二叉树中每个结点所在的层次值置入相应的 level 域,并按前序序列顺序输出每个结点的值和 level 值。

测试说明

输入样例1: A B H # # # D # I E # # #

输出样例1: A 1 B 2 H 3 D 2 I 3 E 4

输入样例2: A B # # C # #

输出样例2: A 1 B 2 C 2

输入样例3: A B D # # E # # C # #

输出样例3: A 1 B 2 D 3 E 3 C 2

代码 

#include <stdio.h>
#include <stdlib.h>

struct BiNode {
	char data;
	int level;
struct BiNode *lchild, *rchild;
};

struct BiTree {
	struct BiNode *root;
};

struct BiNode* Creat(struct BiNode* bt) {
	char ch;
	scanf(" %c", &ch);
	if (ch == '#')
	return NULL;
	else {
	bt = (struct BiNode*)malloc(sizeof(struct BiNode));
	bt->data = ch;
	bt->lchild = Creat(bt->lchild);
	bt->rchild = Creat(bt->rchild);
}
	return bt;
}

void level(struct BiNode* bt, int l) {
	//TODO 将bt中level设置成当前层次值并打印、继续递归左右节点
	//=======begin======
	if (bt == NULL)
	{
		return;
	}
	else
	{
		printf("%c %d ", bt->data, l);
		level(bt->lchild, ++l);
		level(bt->rchild, l);
	}
	//========end=======
}

void preOrder(struct BiNode* bt) {
	if (bt != NULL) {
	preOrder(bt->lchild);
    if ((bt->lchild == NULL && bt->rchild != NULL) || (bt->lchild != NULL && bt->rchild == NULL)) {
        printf("%c ", bt->data);
    }
    preOrder(bt->rchild);
}
}

int Empty(struct BiTree* tree) {
	if (tree->root == NULL)
	return 1;
	else
	return 0;
}

int main() {
	struct BiTree btree;
	btree.root = Creat(btree.root);
	level(btree.root, 1);
	printf("\n");
	return 0;
}

 第5关:求二叉树中结点个数

任务描述

题目描述: 建立一棵二叉树,用二叉链表存储二叉树,计算二叉树中包含的结点个数。

测试说明

输入描述: 输入的数据只有一组,是一棵二叉树的先序遍历序列,结点的值为一个小写字母,号表示空结点,如输入:a b d e # # f # # # c # #,数据之间空一个格,得到的二叉树如下。

输出描述: 输出二叉树的结点个数,空树输出NULL

输入样例1: a b c # # # d e # # f # # 输出样例16

输入样例2: #                输出样例20

 代码

#include <stdio.h>
#include <stdlib.h>

struct Binode {
	char data;
	struct Binode* lchild;
	struct Binode* rchild;
};

struct Bitree {
	struct Binode* root;
};

struct Binode* Creat(struct Binode* bt) {
	char d;
	scanf(" %c", &d);
	if (d == '#')
	bt = NULL;
	else {
	bt = (struct Binode*)malloc(sizeof(struct Binode));
	bt->data = d;
	bt->lchild = Creat(bt->lchild);
	bt->rchild = Creat(bt->rchild);
}
	return bt;
}

void Release(struct Binode* bt) {
	if (bt != NULL) {
	Release(bt->lchild);
	Release(bt->rchild);
	free(bt);
}
}

int Count(struct Binode* bt) {
	//ToDo 计算节点个数
	//=======begin======
	if (bt == NULL)
	{
		return 0;
	}
	
	return Count(bt->lchild) + Count(bt->rchild) + 1;
	//=======begin======
}

int main() {
	//ToDo 设计主函数 以满足题意需求
	//=======begin======
	struct Bitree btree;
	
	btree.root = Creat(btree.root);
	printf("%d", Count(btree.root));
	Release(btree.root);
	//=======begin======
}

第6关:求二叉树叶子结点数

任务描述

题目描述: 二叉树结点的数据类型是字符型,按先序遍历建立二叉树,求叶子结点的个数。

测试说明

输入描述: 输入扩展二叉树的先序遍历序列,其中空字符为“#”,以空格隔开.

输出描述: 输出叶子结点的个数.

输入样例:

A B D H # # # E # I # # C F J # # # G # #

输出样例:

4

代码 

#include <stdio.h>
#include <stdlib.h>

struct BiNode {
	char data;
struct BiNode* lchild;
struct BiNode* rchild;
};

int j = 0;

struct BiNode* Creat(struct BiNode* bt) {
	//TODO:前序建立二叉树
	//========begin=======
	char ch;
	
	scanf(" %c", &ch);
	
	if (ch == '#')
	{
		bt = NULL;
	}
	else
	{
		bt = (struct BiNode*)malloc(sizeof(struct BiNode));
		bt->data = ch;
		bt->lchild = Creat(bt->lchild);
		bt->rchild = Creat(bt->rchild);
	}
	
	return bt;
	//=========end========
}

void Release(struct BiNode* bt) {
	//TODO:后续销毁二叉树
	//========begin=======
	if (bt != NULL)
	{
		Release(bt->lchild);
		Release(bt->rchild);
		free(bt);
	}
	//=========end========
}

void Preorder(struct BiNode* bt) {
	//TODO:前序遍历求叶子结点数
	//========begin=======
	if (bt == NULL)
	{
		return;
	}
	else
	{
		if (bt->lchild == NULL && bt->rchild == NULL)
		{
			j++;
		}
		
		Preorder(bt->lchild);
		Preorder(bt->rchild);		
	}
	//=========end========
}

int main() {
	struct BiNode* root = NULL;
	root = Creat(root);
	Preorder(root);
	printf("%d\n", j);
	Release(root);
	return 0;
}

 第7关:求二叉树的深度

任务描述

题目描述 采用先序法建立一棵二叉树,设计求该二叉树的深度,二叉树的数据域类型为字符型,扩展二叉树的叶子结点用‘#’表示,要求可以求多棵二叉树的深度,当二叉树的深度为 0 时程序结束。

测试说明

输入描述: 循环输入多棵扩展二叉树的先序遍历序列,每棵树占一行,以回车结束,每棵二叉树中结点之间以空格隔开.

输出描述: 输出各二叉树的深度,每次输出后面都换行.

输入样例:

A B # # C D # E # F # # G H # I K # # # #

A B D H # # I # # E J # # K # # C F L # # M # # G N # # O # #

#

输出样例:

6

4

0

代码 

#include <stdio.h>
#include <stdlib.h>

struct BiNode {
	char data;
struct BiNode* lchild;
struct BiNode* rchild;
};

struct BiTree {
struct BiNode* root;
};

struct BiNode* Creat(struct BiNode* bt) {
	char ch;
	scanf(" %c", &ch);
	if (ch == '#')
	bt = NULL;
	else {
	bt = (struct BiNode*)malloc(sizeof(struct BiNode));
	bt->data = ch;
	bt->lchild = Creat(bt->lchild);
	bt->rchild = Creat(bt->rchild);
}
	return bt;
}

int Depth(struct BiNode* bt) {
	//ToDo 递归求最大深度
	//========BEGIN=======
	if (bt == NULL)
	{
		return 0;
	}
	
	int left = Depth(bt->lchild);
	int right = Depth(bt->rchild);
	
	return left > right ? (left+1) : (right+1);
	//=========END========
}

int main() {
	while (1) {
	struct BiTree A;
	//ToDo 设计主函数 以满足题意
	//========BEGIN=======
	A.root = Creat(A.root);
	
	printf("%d\n", Depth(A.root));	
	
	if (Depth(A.root) == 0)
	{
		break;
	}
	//=========END========
}
	return 0;
}

第8关:二叉树交换左右子树

任务描述

本关任务:二叉树的结点数据域是字符型,空用‘#’表示,按前序遍历建立二叉树,交换二叉树中所有结点的左右子树,再前序遍历输出。

测试说明

输入样例1: A B # # C # #                                 输出样例1: A C B

输入样例2: A B H # # # D C # # I E # # #    输出样例2: A D I E C B H

输入样例3: A B D # # E # # C # #                   输出样例3: A C B E D

代码 

#include <stdio.h>
#include <stdlib.h>

struct BiNode {
    char data;
    struct BiNode* lchild;
    struct BiNode* rchild;
};

struct BiNode* Creat(struct BiNode* bt) {
    char ch;
    scanf(" %c", &ch);
    if (ch == '#')
        return NULL;
    else {
        bt = (struct BiNode*)malloc(sizeof(struct BiNode));
        bt->data = ch;
        bt->lchild = Creat(bt->lchild);
        bt->rchild = Creat(bt->rchild);
    }
    return bt;
}

void Change(struct BiNode* bt) {
	//TODO 交换左右子树 并将子树继续交换
	//==========begin=========
    if (bt == NULL)
    {
    	return;
	}
	else
	{
		struct BiNode* temp = bt->lchild;
		bt->lchild = bt->rchild;
		bt->rchild = temp;
		Change(bt->lchild);
		Change(bt->rchild);
	}
	//===========end==========
}

void Print(struct BiNode* bt) {
	printf("%c ", bt->data);
	if (bt->lchild != NULL)
		Print(bt->lchild);
	if (bt->rchild != NULL)
		Print(bt->rchild);
}

int Empty(struct BiNode* root) {
    if (root == NULL)
        return 1;
    else
        return 0;
}

int main() {
	struct BiNode* root = NULL;
	root = Creat(root);

	if (Empty(root))
		return 0;

	Change(root);
	Print(root);

	return 0;
}

第9关:按中序遍历次序输出二叉树中度为1的结点

任务描述

本关任务:二叉树的结点数据域是字符型,空结点用‘#’表示,按前序遍历建立二叉树,按中序输出二叉树中度为 1 的结点。

测试说明

输入样例1: A B H # # # D # I E # # # 输出样例1: B D I 

输入样例2: A # B # #            输出样例2: A

输入样例3: A B C D # # # # #       输出样例3: C B A

 代码

#include <stdio.h>
#include <stdlib.h>

struct BiNode {
    char data;
    struct BiNode *lchild;
    struct BiNode *rchild;
};

typedef struct BiNode BiNode;

/*前序建立二叉树*/
BiNode *createBiTree() {   
    char ch;
    scanf("%c ", &ch);
    if (ch == '#') {
        return NULL;
    } else {
        BiNode *node = (BiNode *) malloc(sizeof(BiNode));
        node->data = ch;
        node->lchild = createBiTree();
        node->rchild = createBiTree();
        return node;
    }
}
void inOrderTraversal(BiNode *root) {
    /*按中序输出二叉树中度为1的结点*/
	/*=========begin========*/
    if (root == NULL)
    {
    	return;
	}
	else
	{
		inOrderTraversal(root->lchild);
		
		if ((root->lchild == NULL && root->rchild != NULL) || (root->lchild != NULL && root->rchild == NULL))
		{
			printf("%c ", root->data);
		}
		
		inOrderTraversal(root->rchild);
	}
	/*==========end========*/
}

int main() {
    
    BiNode *root = createBiTree();    /*前序建立二叉树*/
    
    inOrderTraversal(root);           /*中序输出度为1的结点*/
    printf("\n");
    return 0;
}

  • 20
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

布凯彻-劳斯基

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值