浅学C++(5)数据结构与算法(初识树型结构、二叉树)

本文详细介绍了树的基本概念,包括树的表示方式、专业术语、存储方法以及二叉树的定义、性质、特殊类型。此外,还探讨了二叉树的遍历、操作和存储实现,包括前序、中序、后序遍历以及顺序和链式存储。文章还提供了有序二叉树的插入、查找、删除等操作的代码示例。
摘要由CSDN通过智能技术生成
树型结构:
    1,树的基本概念
        一种表示层次关系(一对多)的数据结构
        有且只有一个特定的节点,该节点没有前驱节点,被称为根节点 root
        剩余的n个互不相交的子集,其中每个子集也都是一棵树,都被称为根节点的子树
        tap:树形结构具有递归性(树中有树)

    2,树的表示方式
        倒悬树、嵌套法、凹凸法

    3,树的专业术语
        节点:组成一棵树的基础元素,同时他也是一棵树
        节点的度:该节点子树的数量
        树的度:树中所有节点的度的最大值
        树的密度:树中所有节点的数量
        树的深度(高度):树的最大层次数(从1开始)
        节点的层次:根节点的层次为1,它的孩子层次为2,它的孩子的孩子层次为3,以此类推
        叶子节点:节点的的度为0的节点
        双亲节点和孩子节点:节点的子树被称为该节点的孩子节点,该节点就是孩子节点的双亲节点
        兄弟节点:具有同一个双亲节点的节点互为兄弟节点
        堂兄弟:双亲节点互为兄弟节点
        祖先:从根节点出发到该节点,路径上经过的所有节点都称为该节点的祖先
        子孙:一个节点的子树中任意一个节点都是它的子孙

    4,树的存储
        树可以顺序存储、链式存储,还可以混合存储
        可以根据存储的信息不同,树可以有以下存储方式:
            双亲表示法: 顺序
                位置    data    双亲下标
                0       A       -1
                1       B       0
                2       C       0
                3       D       1
                4       E       1
                5       F       1
                6       G       2
                7       H       4
                优点:方便找到双亲
                缺点:查找孩子节点麻烦

            孩子表示法:
                顺序:
                位置    data    son_arr(存储子节点的数组)
                0       A       1,2
                1       B       3,4,5
                2       C       6
                3       D       
                4       E       7
                5       F       
                6       G       
                7       H      
                优点:查找孩子节点方便
                缺点:找双亲不方便,浪费内存
                链式:
                位置    data    listHead(存储子节点的链表)
                0       A       1->2
                1       B       3->4->5
                2       C       6
                3       D       N
                4       E       7
                5       F       N
                6       G       N
                7       H       N
                优点:查找孩子节点方便,节约内存
                缺点:找双亲不方便

            兄弟表示法:
                链式
                双亲只存储第一个子节点 数据 链式指向所有的兄弟节点
                优点:可以方便找到所有的兄弟节点
                缺点:找双亲麻烦
            tap:普通树不常用,所以使用二叉树
二叉树:
        一种常见的数据结构,比普通树处理起来要简单,而且树也比较简单转换成二叉树
        定义: 节点的度最多为2的树型结构
            二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、
        被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,
        一个元素也称作一个节点。

        特殊的二叉树类型:
            满二叉树:每层的节点数都是2^(i-1) (i>=1)为层数 
            完全二叉树:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。需要注意的是
                       满二叉树肯定是完全二叉树,而完全二叉树不一定是满二叉树。

        二叉树的重要性质:
            性质1:二叉树的第i层上至多有2^(i-1) (i≥1)个节点 
            性质2:深度为h的二叉树中至多含有2^h-1个节点 
            性质3:若在任意一棵二叉树中,有n0个叶子节点,有n2个度为2的节点,则必有n0=n2+1 到
            性质4:具有n个节点的满二叉树深为log2n+1。
            性质5:若对一棵有n个节点的完全二叉树进行顺序编号(1≤i≤n),那么,对于编号为i(i≥1)的节点:
                当i=1时,该节点为根,它无双亲节点
                当i>1时,该节点的双亲节点的编号为i/2 
                若2i≤n,则有编号为2i的左节点,否则没有左节点
                若2i+1≤n,则有编号为2i+1的右节点,否则没有右节点 

        ABCD#EF#G##H
        二叉树的操作:
            构建、销毁、遍历、高度、密度、插入、删除、查询、求左、求右、求根

        二叉树的存储:
            顺序存储:必须要按照完全二叉树的格式,把每个节点按照从上到下、从左到右顺序依次存入连续内存
                     如果有空位置则使用特殊数据代替存入
                     数据项:
                        存储节点内存的首地址
                        容量

            链式存储:由一个个的链式节点组成,每个节点就是一棵树
                节点数据项:
                    数据
                    左子树指针
                    右子树指针


        二叉树的遍历:
            前序遍历:根、左、右
            中序遍历:左、根、右
            后序遍历:左、右、根
            tap:前、中、后序由根节点决定,并且左右子树的遍历顺序不会改变,通过前序+中序 或者 后续+中序 就可以还原一棵树
            层序遍历:从上到下、从左到右依次遍历 配合队列

有序二叉树的各功能实现

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

//有序二叉树

typedef struct TreeNode
{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
}TreeNode;

//创建
TreeNode* create_tree_node(int data)
{
	TreeNode* node = malloc(sizeof(TreeNode));
	node->data = data;
	node->left = NULL;
	node->right = NULL;
	return node;
}
//加入依赖
void _insert_tree(TreeNode** root,TreeNode* node)
{
	if(NULL == *root)
	{
		*root = node;	
		return;
	}
	if(node->data < (*root)->data)
		_insert_tree(&((*root)->left),node);	
	else
		_insert_tree(&((*root)->right),node);
		
}
//插入
void insert_tree(TreeNode** root,int data)
{
	_insert_tree(root,create_tree_node(data));
}

//中序遍历 排序 从小到大
void ldr_show(TreeNode* root)
{
	if(NULL == root) return;
	ldr_show(root->left);
	printf("%d ",root->data);
	ldr_show(root->right);
}
void dlr_show(TreeNode* root)
{
	if(NULL == root) return;
	printf("%d ",root->data);
	dlr_show(root->left);
	dlr_show(root->right);
}
void lrd_show(TreeNode* root)
{
	if(NULL == root) return;
	lrd_show(root->left);
	lrd_show(root->right);
	printf("%d ",root->data);
}

//查找
bool query_tree(TreeNode* root,int data)
{
	if(NULL == root) return false;
	if(root->data == data) return true;	
	if(data < root->data)
		query_tree(root->left,data);	
	else
		query_tree(root->right,data);
}

//密度
int density_tree(TreeNode* root)
{
	if(NULL == root) return 0;
	return density_tree(root->left)+density_tree(root->right)+1;
}

//高度
int high_tree(TreeNode* root)
{
	if(NULL == root) return 0;
	int lh = density_tree(root->left);
	int rh = density_tree(root->right);
	return lh>rh?lh+1:rh+1;
}

//销毁
void destory_tree(TreeNode* root)
{
	if(NULL == root) return;
	destory_tree(root->left);
	destory_tree(root->right);
	free(root);
}

bool _access_tree(TreeNode* root,int* cnt,size_t index,int* ptr)
{
	if(NULL == root) return false;
	bool lfalg = _access_tree(root->left,cnt,index,ptr);
	if(lfalg) return true;
	if((*cnt)++ == index) 
	{
		*ptr = root->data;	
	}
	return  _access_tree(root->right,cnt,index,ptr);

}
//按中序访问
bool access_tree(TreeNode* root,size_t index,int* ptr)
{
	int cnt = 0;
	return _access_tree(root,&cnt,index,ptr);
}

//按值删除
bool del_value_tree(TreeNode** root,int data)
{
	if(NULL == *root) return false;
	if(data == (*root)->data)
	{
		TreeNode* temp = *root;
		*root = temp->left;
		_insert_tree(root,temp->right);
		free(temp);
		return true;
	}
	if(data < (*root)->data)
		return del_value_tree(&(*root)->left,data);
	else
		return del_value_tree(&(*root)->right,data);
}

链式二叉树的功能实现

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

#define TREE_TYPE char
#define EMPTY '#'
#define END '\0'

//设计树的节点
typedef struct TreeNode
{
	TREE_TYPE data;
	struct TreeNode* left;
	struct TreeNode* right;
}TreeNode;

//创建树节点
TreeNode* creatr_tree_node(TREE_TYPE data)
{
	TreeNode* node = malloc(sizeof(TreeNode));
	node->data = data;
	node->left = NULL;
	node->right = NULL;
	return node;
}
/*
//构建二叉树 构建前序 ABC#G###DE##F##
TreeNode* create_tree(void)
{
	TREE_TYPE data = 0;
	scanf("%c",&data);
	if(EMPTY == data) return NULL;
	TreeNode* node = creatr_tree_node(data);
	node->left = create_tree();
	node->right = create_tree();
	return node;
}*/

//构建依赖
TreeNode* _create_tree(TREE_TYPE** str)
{
	if(EMPTY == **str || END == **str) return NULL;
	TreeNode* node = creatr_tree_node(**str);
	*str+=1;
	node->left = _create_tree(str);
	*str+=1;
	node->right = _create_tree(str);
	return node;
}
TreeNode* create_tree(TREE_TYPE* str)
{
	TreeNode* node = _create_tree(&str);
	return node;
}

//前序遍历
void dlr_show(TreeNode* root)
{
	if(NULL == root) return;
	printf("%c",root->data);
	dlr_show(root->left);
	dlr_show(root->right);
}
//中序遍历
void ldr_show(TreeNode* root)
{
	if(NULL == root) return;
	ldr_show(root->left);
	printf("%c",root->data);
	ldr_show(root->right);
}
//后序遍历
void lrd_show(TreeNode* root)
{
	if(NULL == root) return;
	lrd_show(root->left);
	lrd_show(root->right);
	printf("%c",root->data);
}

//树的高度
int high_tree(TreeNode* root)
{
	if(NULL == root) return 0;
	int lh = high_tree(root->left);
	int rh = high_tree(root->right);
	return lh>rh?lh+1:rh+1;
}

//树的密度
int denstity_tree(TreeNode* root)
{
	if(NULL == root) return 0;	
	return denstity_tree(root->left)+denstity_tree(root->right)+1;
}

//求左子树
TreeNode* left_tree(TreeNode* root,TREE_TYPE data)
{
	if(NULL == root) return NULL;
	if(data == root->data) return root->left;
	TreeNode* lnode = left_tree(root->left,data);
	if(NULL != lnode) return lnode;
	TreeNode* rnode = left_tree(root->right,data);
	return rnode;
}

//插入
bool insert_tree(TreeNode* root,TREE_TYPE pdata,TREE_TYPE data)
{
	if(NULL == root) return false;
	if(root->data == pdata)
	{
		if(NULL == root->left)
		{
			return root->left = creatr_tree_node(data);
		}
		if(NULL == root->right)
		{
			return root->right = creatr_tree_node(data);	
		}
	}
	bool lfalg = insert_tree(root->left,pdata,data);
	bool rfalg = insert_tree(root->right,pdata,data);
	return lfalg || rfalg;
}

//删除 只删除叶子节点
bool del_tree(TreeNode** root,TREE_TYPE data)
{
	if(NULL == *root) return false;
	if((*root)->data == data)
	{
		if((*root)->left || (*root)->right)	return false;
		free(*root);
		*root = NULL;
		return true;
	}
	bool lfalg = del_tree(&(*root)->left,data);
	bool rfalg = del_tree(&(*root)->right,data);
	return lfalg || rfalg;
}

//销毁
void destory_tree(TreeNode* root)
{
	if(NULL == root) return;
	destory_tree(root->left);
	destory_tree(root->right);
	free(root);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值