数据结构-树

数据结构- 树

一、树的说明

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. 先遍历孩子,后遍历父亲

程序代码

//tree_link.h
#ifndef __TREE_LINK_H__
#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;
}

//

//main.c
#include <stdio.h>
#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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值