• 一步一步学数据结构之1--n(通用树)


     

           今天来看大家介绍树,树是一种非线性的数据结构,树是由n个结点组成的有限集合,如果n=0,称为空树;如果n>0,则:有一个特定的称之为根的结点,它只有直接后继,但没有直接前驱;除根以外的其他结点划分为m个互不相交的有限集合,每个集合又是一棵树,并且称之为根的子树。

          如图

                 

          树的一些基本概念

    l 树的结点包含一个数据以及若干指向子树的分支

    l 结点拥有的子树数称为结点的度

    u 度为0的结点称为叶结点

    u 度不为0的结点称为分支结点

    l 树的度定义为所有结点中的度的最大值

    l 结点的直接后继称为该结点的孩子

    u 相应的,该结点称为孩子的双亲

    l 结点的孩子的孩子的.....称为该结点的子孙

    u 相应的,该结点称为子孙的祖先

    l 同一个双亲的孩子之间互称兄弟

    l 树中结点的最大层次称为树的深度或高度

    l 森林是由n(n>=0)棵互不相交的树组成的集合

    在这里,我们用通用树结构来给大家介绍树的一些基本操作和操作实现。通用树的存储结构为:

      

    这里介绍通用树的常用操作:

    l 创建树

    l 销毁树

    l 清空树

    l 插入结点到树中

    l 删除结点

    l 获取某个结点

    l 获取根结点

    l 获取树的高度

    l 获取总结点数

    l 获取树的度

    l 输出树

    代码总分为三个文件:

    GTree.h : 放置功能函数的声明,以及树的声明,以及数据的声明 

    GTree.c : 放置功能函数的定义,以及树结点和组织链表结点的定义

    Main.c   : 主函数,使用功能函数完成各种需求,一般用作测试

    整体结构图为:

     

    这里详细说下插入结点操作,删除结点操作:

     

    插入结点操作:

    如图:

      

    删除结点操作:

    如图:

    OK! 上代码:

    GTree.h : 

    #ifndef _GTREE_H_
    #define _GTREE_H_
    
    typedef void GTree;
    typedef void GTreeData;
    typedef void (GTree_Printf)(GTreeData*);
    
    GTree* GTree_Create();
    
    void GTree_Destroy(GTree* tree);
    
    void GTree_Clear(GTree* tree);
    
    int GTree_Insert(GTree* tree, GTreeData* data, int pPos);
    
    GTreeData* GTree_Delete(GTree* tree, int pos);
    
    GTreeData* GTree_Get(GTree* tree, int pos);
    
    GTreeData* GTree_Root(GTree* tree);
    
    int GTree_Height(GTree* tree);
    
    int GTree_Count(GTree* tree);
    
    int GTree_Degree(GTree* tree);
    
    void GTree_Display(GTree* tree, GTree_Printf* pFunc, int gap, char div);
    
    #endif
    


     

    GTree.c : 

    #include <stdio.h>
    #include <malloc.h>
    #include "GTree.h"
    #include "LinkList.h"
    
    typedef struct _tag_GTreeNode GTreeNode;
    struct _tag_GTreeNode
    {
    	GTreeData* data;
    	GTreeNode* parent;
    	LinkList* child;
    };
    
    typedef struct _tag_TLNode TLNode;
    struct _tag_TLNode
    {
    	LinkListNode header;
    	GTreeNode* node;
    };
    
    GTree* GTree_Create()
    {
    	return LinkList_Create();
    }
    
    void GTree_Destroy(GTree* tree)
    {
    	GTree_Clear(tree);
    	
    	LinkList_Destroy(tree);
    }
    
    void GTree_Clear(GTree* tree)
    {
    	GTree_Delete(tree, 0);
    }
    
    int GTree_Insert(GTree* tree, GTreeData* data, int pPos)
    {
    	LinkList* list = (LinkList*)tree;
    	
    	int ret = (NULL!=list) && (NULL!=data) && (pPos<LinkList_Length(list));
    	
    	if(ret)
    	{
    		TLNode* trNode = (TLNode*)malloc(sizeof(TLNode));
    		TLNode* cldNode = (TLNode*)malloc(sizeof(TLNode));
    		TLNode* pNode = (TLNode*)LinkList_Get(list, pPos);
    		
    		GTreeNode* cNode = (GTreeNode*)malloc(sizeof(GTreeNode));
    		
    		ret = (NULL!=trNode) && (NULL!=cldNode) && (NULL!=cNode);
    		
    		if(ret)
    		{
    			cNode->data = data;
    			cNode->parent = NULL;
    			cNode->child = LinkList_Create();
    			
    			trNode->node = cNode;
    			cldNode->node = cNode;
    			
    			LinkList_Insert(list, (LinkListNode*)trNode, LinkList_Length(list));
    		
    			if(NULL != pNode)
    			{
    				cNode->parent = pNode->node;
    				
    				LinkList_Insert(pNode->node->child, (LinkListNode*)cldNode, LinkList_Length(pNode->node->child));
    			}
    			else
    			{
    				free(cldNode);
    			}
    		}
    		else
    		{
    			free(trNode);
    			free(cldNode);
    			free(cNode);
    		}
    	}
    	
    	return ret;
    }
    
    static int recursive_height(GTreeNode* node)
    {
    	int ret = 0;
    	
    	if(NULL != node)
    	{
    		int subHeight = 0;
    		int i = 0;
    		
    		for(i=0; i<LinkList_Length(node->child); i++)
    		{
    			TLNode* trNode = (TLNode*)LinkList_Get(node->child, i);
    			
    			subHeight = recursive_height(trNode->node);
    			
    			if(ret < subHeight)
    			{
    				ret = subHeight;
    			}
    		}
    		
    		ret = ret+1;
    	}
    	
    	return ret;
    }
    
    
    int GTree_Height(GTree* tree)
    {
    	TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);
    	
    	int ret = 0;
    	
    	if(NULL != trNode)
    	{
    		ret = recursive_height(trNode->node);
    	}
    	
    	return ret;
    }
    
    static void recursive_delete(LinkList* list, GTreeNode* node)
    {
    	if((NULL != list) && (NULL != node))
    	{
    		GTreeNode* parent = node->parent;
    		
    		int index = -1;
    		int i = 0;
    		
    		for(i=0; i<LinkList_Length(list); i++)
    		{
    			TLNode* trNode = (TLNode*)LinkList_Get(list, i);
    			
    			if(node == trNode->node)
    			{
    				LinkList_Delete(list, i);
    				free(trNode);
    				index = i;
    				
    				break;
    			}
    		}
    		
    		if(0 <= index)
    		{
    			if(NULL != parent)
    			{
    				for(i=0; i<LinkList_Length(parent->child); i++)
    				{
    					TLNode* trNode = (TLNode*)LinkList_Get(parent->child, i);
    					
    					if(node == trNode->node)
    					{
    						LinkList_Delete(parent->child, i);
    						free(trNode);
    						
    						break;	
    					}
    				}
    			}
    			
    			while(0 < LinkList_Length(node->child))
    			{
    				TLNode* trNode = (TLNode*)LinkList_Get(node->child, 0);
    				
    				recursive_delete(list, trNode->node);
    			}
    			
    			LinkList_Destroy(node->child);
    			free(node);
    		}
    	}
    }
    
    GTreeData* GTree_Delete(GTree* tree, int pos)
    {
    	TLNode* trNode = (TLNode*)LinkList_Get(tree, pos);
    	
    	GTreeData* ret = NULL;
    	
    	if(NULL != trNode)
    	{
    		ret = trNode->node->data;
    		
    		recursive_delete(tree, trNode->node);
    	}
    	
    	return ret;
    }
    
    GTreeData* GTree_Get(GTree* tree, int pos)
    {
    	TLNode* trNode = (TLNode*)LinkList_Get(tree, pos);
    	
    	GTreeData* ret = NULL;
    	
    	if(NULL != trNode)
    	{
    		ret = trNode->node->data;
    	}
    	
    	return ret;
    }
    
    GTreeData* GTree_Root(GTree* tree)
    {
    	return GTree_Delete(tree, 0);
    }
    
    int GTree_Count(GTree* tree)
    {
    	return LinkList_Length(tree);
    }
    
    static int recursive_degree(GTreeNode* node)
    {
    	int ret = -1;
    	
    	if(NULL != node)
    	{
    		int subDegree = 0;
    		int i = 0;
    		
    		ret = LinkList_Length(node->child);
    		
    		for(i=0; i<LinkList_Length(node->child); i++)
    		{
    			TLNode* trNode = (TLNode*)LinkList_Get(node->child, i);
    			
    			subDegree = recursive_degree(trNode->node);
    			
    			if(ret < subDegree)
    			{
    				ret = subDegree;
    			}
    		}
    	}
    	
    	return ret;
    }
    
    int GTree_Degree(GTree* tree)
    {
    	TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);
    	
    	int ret = -1;
    	
    	if(NULL != trNode)
    	{
    		ret = recursive_degree(trNode->node);
    	}
    	
    	return ret;
    }
    
    static void recursive_display(GTreeNode* node, GTree_Printf* pFunc, int format, int gap, char div)
    {
    	int i = 0;
    	
    	if((NULL != node) && (NULL != pFunc))
    	{
    		for(i=0; i<format; i++)
    		{
    			printf("%c", div);
    		}
    		
    		pFunc(node->data);
    		printf("
    ");
    		
    		for(i=0; i<LinkList_Length(node->child); i++)
    		{
    			TLNode* trNode = (TLNode*)LinkList_Get(node->child, i);
    			
    			recursive_display(trNode->node, pFunc, format+gap, gap, div);
    		}
    	}
    }
    
    void GTree_Display(GTree* tree, GTree_Printf* pFunc, int gap, char div)
    {
    	TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);
    	
    	if((NULL != trNode) && (NULL != pFunc))
    	{
    		recursive_display(trNode->node, pFunc, 0, gap, div);
    	}
    }
    


     

    Main.c  :

                 

    #include <stdio.h>
    #include "GTree.h"
    
    void printf_data(GTreeData* data)
    {
    	printf("%c", (int)data);
    }
    
    int main(void)
    {
    	GTree* tree = GTree_Create();
    	
    	int i = 0;
    	
    	GTree_Insert(tree, (GTreeData*)'A', -1);
    	GTree_Insert(tree, (GTreeData*)'B', 0);
    	GTree_Insert(tree, (GTreeData*)'C', 0);
    	GTree_Insert(tree, (GTreeData*)'D', 0);
    	GTree_Insert(tree, (GTreeData*)'E', 1);
    	GTree_Insert(tree, (GTreeData*)'F', 1);
    	GTree_Insert(tree, (GTreeData*)'H', 3);
    	GTree_Insert(tree, (GTreeData*)'I', 3);
    	GTree_Insert(tree, (GTreeData*)'J', 3);
    	
    	printf("Tree Height: %d
    ", GTree_Height(tree));
    	printf("Tree Degree: %d
    ", GTree_Degree(tree));
    	printf("Full Tree:
    ");
    	
    	GTree_Display(tree, printf_data, 2, '-');
    	
    	printf("Get Tree Data: 
    ");
    	
    	for(i=0; i<GTree_Count(tree); i++)
    	{
    		printf_data(GTree_Get(tree, i));
    		printf("
    ");
    	}
    	
    	printf("Get Root Data: 
    ");
    	
    	printf_data(GTree_Root(tree));
    	printf("
    ");
    	
    	GTree_Delete(tree, 3);
    	printf("After Deleting D: 
    ");
    	GTree_Display(tree, printf_data, 2, '-');
    	
    	GTree_Clear(tree);
    	
    	printf("After Clearing Tree:
    ");
    	
    	GTree_Display(tree, printf_data, 2, '.');
    	
    	GTree_Destroy(tree);
    	
    	return 0;
    }


  • 相关阅读:
    红黑树以及与AVL树的区别
    yum安装mysql
    sql注入攻击
    http keep-alive
    csrf和xss
    点击事件跳转QQ 添加好友
    引入百度地图及出现的问题
    node 出现npm ERR! code ERR_TLS_CERT_ALTNAME_INVALID npm ERR! errno ERR_TLS_CERT_ALTNAME_INVALID npm ERR! request to https://registry.cnpmjs.org/vue-cli failed, reason:
    正则表达式校验-大于0的所有数,小数点后保留两位小数和正整数
    vue项目引入富文本编辑器(回显)
  • 原文地址:https://www.cnblogs.com/riskyer/p/3253785.html
Copyright © 2020-2023  润新知