数据结构- 树
一、树的说明
1. 树是一种组织数据的方式。
2. 如文件浏览器中的文件组织方式:文件夹、文件,文件夹中还有文件夹、文件。
二、树的模型
1. A是这棵树的根节点。
2.(B、E、F)组成了一棵树,属于这棵大树的子树。
3. E、F是B节点的子节点,所以B是E、F的父节点,E、F是兄弟节点。
三、树的设计
1. 节点数据结构
2. 树的节点
struct tree_link {
struct tree_link* parent; // 指向父亲
struct tree_link* brother; // 指向下一个兄弟
struct tree_link* children; //指向孩子,链表头
};
四、树的构建
1. 新建宿主数据节点。
2. 声明一个树节点指针(root_tree_link)保存第一个宿主节点的树节点。
3. 插入树节点。
4. 移除树中的节点。
五、树的遍历
1. 先遍历父亲,后遍历孩子;
2. 先遍历孩子,后遍历父亲
程序代码
#define __TREE_LINK_H__
#include <string.h>
struct tree_link
{
struct tree_link* parent;
struct tree_link* brother;
struct tree_link* children;
};
//父子关联
void link_to_parent(struct tree_link* link, struct tree_link* parent);
//移除节点
void remove_from_parent(struct tree_link* link);
//通过link的内存地址反推data_node的内存地址
//基地址 + offset = &(基地址->link)
//offset = &(NULL)->link
#define TLINK_TO_ElEM(link_ptr, elem_type, mem_name) \
( (elem_type*)(((unsigned char*)link_ptr) - (int)(&(((elem_type*)NULL)->mem_name))) )
#endif
//tree_link.c
#include "tree_link.h"
void link_to_parent(struct tree_link* link, struct tree_link* parent)
{
if (parent == NULL){return;}
//认父
link->parent = parent;
//认子
struct tree_link** walk = &parent->children;
while (*walk)
{
walk
= &(*walk)->brother;
}
*walk = link;
}
void remove_from_parent(struct tree_link* link)
{
//如果link没有父亲 return
if (link->parent == NULL){return;}
//断绝父子关系
struct tree_link** walk = &link->parent->children;
while (*walk)
{
if
(*walk == link)
{
//找到则
*walk
= link->brother;
link->brother
= NULL;
break;
}
//没有找到则指向下一个兄弟节点,继续找
walk
= &(*walk)->brother;
}
link->parent = NULL;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <string.h>
#include "tree_link.h"
struct data_node
{
char name[16];
//树的节点
struct tree_link link;
};
struct data_node* alloc_data_node(const char* name)
{
struct data_node* node = malloc(sizeof(struct data_node));
memset(node, 0, sizeof(struct data_node));
strcpy(node->name,name);
return node;
}
void trans_data_from_tree(struct tree_link* root)
{
if (root == NULL){return;}
//通过link的内存地址反推data_node的内存地址
struct data_node* node = TLINK_TO_ElEM(root, struct data_node, link);
printf("%s\n", node->name);
//遍历所有孩子节点
struct tree_link* walk = root->children;
while (walk)
{
trans_data_from_tree(walk);
walk = walk->brother;
}
}
int main(int argc, char** argv)
{
//声明一个tree_link类型指针,来存放data_node类型root节点下的link对象地址
struct tree_link* root_tree_link = NULL;
//在堆上开辟一块内存来存放一个data_node,名为root
struct data_node* root = alloc_data_node("A");
root_tree_link = &root->link;
//开辟另一块内存存放其他data_node
struct data_node* node = NULL;
struct data_node* node_b = NULL;
struct data_node* node_c = NULL;
node = alloc_data_node("B");
node_b = node;
link_to_parent(&node->link, root_tree_link);
//创建新节点c
node = alloc_data_node("C");
node_c = node;
link_to_parent(&node->link, root_tree_link);
//创建新节点d
node = alloc_data_node("D");
link_to_parent(&node->link, root_tree_link);
//创建新节点e
node = alloc_data_node("E");
link_to_parent(&node->link, &node_b->link);
//创建新节点f
node = alloc_data_node("F");
link_to_parent(&node->link, &node_b->link);
//创建新节点f
node = alloc_data_node("G");
link_to_parent(&node->link, &node_c->link);
//从tree中移除一个node
remove_from_parent(&node->link);
//遍历数据
trans_data_from_tree(root_tree_link);
system("pause");
return 0;
}