目录:
- 代码:
- 分析:
- 汇编:
代码:
LinkList.h
LinkList.c
线性表
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;
};static void recursive_display(GTreeNode* node, GTree_Printf* pFunc, int format, int gap, char div)
{int i = 0;if( (node != NULL) && (pFunc != NULL) )//判断节点与函数指针不为空{for(i=0; i<format; i++)//format 大于0时将输出格式符 div{printf("%c", div);}pFunc(node->data);//执行函数(进行节点数据输出)printf("\n");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);//在每层子节点以2个格式占位符递增}}
}static void recursive_delete(LinkList* list, GTreeNode* node)//定义递归删除节点函数
{if( (list != NULL) && (node != NULL) )//判断链表与树节点不为空{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( trNode->node == node )//如果该节点是要删除的树节点{LinkList_Delete(list, i);//将该节点从链表中删除free(trNode);//将该节点的空间释放(就是Insert函数中trNode申请的)index = i;//取得删除的下标break;}}if( index >= 0 )//如果在链表中删除了节点{ if( parent != NULL )//如果父节点不为空{for(i=0; i<LinkList_Length(parent->child); i++)//在父节点中的子链表中找到要删除的节点{TLNode* trNode = (TLNode*)LinkList_Get(parent->child, i);//在父节点中的子链表中取出要删除的节点if( trNode->node == node )//如果取出的节点是要删除的节点 {LinkList_Delete(parent->child, i);//将该节点从父节点的子链表中删除free(trNode);//该空间释放(就是Insert函数中cldNode申请的)break;}} }while( LinkList_Length(node->child) > 0 )//如果删除节点还有子节点{TLNode* trNode = (TLNode*)LinkList_Get(node->child, 0);//取出删除节点中的子节点recursive_delete(list, trNode->node);//将要每个子节点执行同样操作}LinkList_Destroy(node->child);//这必须放在while后面,free(node);//释放树节点空间(就是Insert函数中cNode申请的)这必须放在while后面}}
}static int recursive_height(GTreeNode* node)//定义递归计算树高度函数
{int ret = 0;if( node != NULL )//如果节点不为空{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+1。然后返回到上一个节点就相当再加上自己本身的这层}}ret = ret + 1;//加一 表示有一层子节点,只要node(传来的子节点)不为空必须加一}return ret;
}static int recursive_degree(GTreeNode* node)//定义递归计算树度数函数
{
int ret = -1;if( node != NULL )//如果节点不为空{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;
}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 = (list != NULL) && (data != NULL) && (pPos < LinkList_Length(list));//判断表不为空插入的数据不为空与pPos正常if( ret )//条件成功{TLNode* trNode = (TLNode*)malloc(sizeof(TLNode));//新建树节点与链表关联类型// 注意:如果是下面pNode==NULL 。比如插入第一个节点时,后面这个cldNode申请的空间释放不了TLNode* cldNode = (TLNode*)malloc(sizeof(TLNode));//新建树节点与链表关联类型TLNode* pNode = (TLNode*)LinkList_Get(list, pPos);//获取出pPos位置的节点GTreeNode* cNode = (GTreeNode*)malloc(sizeof(GTreeNode));//新建一个树类型节点ret = (trNode != NULL) && (cldNode != NULL) && (cNode != NULL);//判断三个申请的空间成功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( pNode != NULL )//如果该位置本来有节点{cNode->parent = pNode->node;//将该位置本来有的节点赋给新建树节点的的父节点//使用树节点与链表关联类型将新建节点插入到该位置本来节点的子链表最后一个位置LinkList_Insert(pNode->node->child, (LinkListNode*)cldNode, LinkList_Length(pNode->node->child));}}else//如果条件不成功将申请的空间释放{free(trNode);free(cldNode);free(cNode);}}return ret;
}GTreeData* GTree_Delete(GTree* tree, int pos)//定义删除节点函数
{TLNode* trNode = (TLNode*)LinkList_Get(tree, pos);//从链表中获取出删除位置节点GTreeData* ret = NULL;//定义指向删除节点中存放的数据的指针if( trNode != NULL )//如果有该位置节点{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( trNode != NULL ){ret = trNode->node->data;//取得节点数据指针}return ret;//返回点中存放的数据指针
}GTreeData* GTree_Root(GTree* tree)//定义获取根节点数据函数
{return GTree_Get(tree, 0);//调用获取节点数据函数
}int GTree_Height(GTree* tree)//定义获取树的高度函数
{TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);//取出第一个节点(根节点)int ret = 0;if( trNode != NULL ){ret = recursive_height(trNode->node);//调用递归计算高度}return ret;
}int GTree_Count(GTree* tree)//定义返回树节点总数量函数
{return LinkList_Length(tree);//返回链表数量
}int GTree_Degree(GTree* tree)//定义获取树的度数函数
{TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);//取得根节点int ret = -1;if( trNode != NULL ){ret = recursive_degree(trNode->node);//调用递归计算度数}return ret;
}void GTree_Display(GTree* tree, GTree_Printf* pFunc, int gap, char div)//定义给每个节点数据进行操作函数
{TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);//取得根节点if( (trNode != NULL) && (pFunc != NULL) )//根节点与函数指针不为空{ 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(int argc, char *argv[])
{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\n", GTree_Height(tree));printf("Tree Degree: %d\n", GTree_Degree(tree));printf("Full Tree:\n");GTree_Display(tree, printf_data, 2, ' ');printf("Get Tree Data:\n");for(i=0; i<GTree_Count(tree); i++){printf_data(GTree_Get(tree, i));printf("\n");}printf("Get Root Data:\n");printf_data(GTree_Root(tree));printf("\n");GTree_Delete(tree, 3);printf("After Deleting D:\n");GTree_Display(tree, printf_data, 2, '-');GTree_Clear(tree);printf("After Clearing Tree:\n");GTree_Display(tree, printf_data, 2, '.');GTree_Destroy(tree);getchar();return 0;
}
分析:
汇编: