数据结构之树的一些基本操作

是由根结点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。父子关系在树的结点之间建立了一个层次结构。在这种层次结构中有一个结点具有特殊的地位,这个结点称为该树的根结点,或称为树根。
头文件 tree.h

#ifndef __TREE_H__
#define __TREE_H__

#include "error.h"

struct _treeNode;                   // 结构体声明

// 孩子结点链表的类型
typedef struct _childNode
{
    struct _treeNode * childNode;
    struct _childNode* next;        // 指向孩子结点链表下一个元素
}ChildNode;

// 树节点类型
typedef char TreeData;
typedef struct _treeNode
{
    TreeData data;
    struct _treeNode * parent;      // 指向父节点的指针
    struct _treeNode * next;        // 指向链表的下一个结点
    struct _childNode* childList;   // 孩子链表的头节点
    int degree;                     // 结点的度
}TreeNode;

typedef struct _tree
{
    struct _treeNode* head;         // 树链表的头节点
    int len;                        // 树结点个数
}Tree;

// 定义一个函数指针类型
typedef void(*TreePrint)(TreeNode *node);

Tree* Create_Tree();

// pos 代表要插入结点父亲结点的位置
// 约定:
// 1 新插入的结点插入在当前父亲结点所有孩子的右边
// 2 根节点的位置是 0
int Insert_Tree (Tree* tree, TreeData data, int pos);

// 打印树
void Display (Tree* tree, TreePrint pFunc);

// 删除结点
int Delete (Tree* tree, int pos, TreeData *x);

// 求指定位置树结点的值
int Tree_Get (Tree* tree, int pos, TreeData *x);

// 清空树中所有的节点
int Tree_Clear (Tree* tree);

// 树的销毁 
void Tree_Destroy   (Tree* tree);

// 获取根节点的地址
TreeNode* Tree_Root (Tree* tree);

// 求树的结点个数
int Tree_Count  (Tree* tree);

// 求树的高度
int Tree_Height (Tree* tree);

// 求树的度
int Tree_Degree (Tree* tree);

// 打印
void printA (TreeNode* node);

#endif  // __TREE_H__


源文件 tree.c

#include "tree.h"
#include <stdlib.h>

Tree *Create_Tree()
{
    // 创建树节点
    Tree* tree = (Tree*) malloc(sizeof(Tree)/sizeof(char));
    if (NULL == tree)
    {
        errno = MALLOC_ERROR;
        return NULL;
    }

    // 给树结点链表创建头节点
    tree->head = (TreeNode*) malloc(sizeof(TreeNode)/sizeof(char));
    if (NULL == tree->head)
    {
        errno = MALLOC_ERROR;
        free (tree);
        return NULL;
    }

    tree->head->parent    = NULL;
    tree->head->childList = NULL;
    tree->head->next      = NULL;   // 代表树中没有结点

    // 空树结点为0
    tree->len = 0;

    return tree;
}

int Insert_Tree (Tree* tree, TreeData data, int pos)
{
    if (NULL == tree || pos < 0 || pos > tree->len)
    {
        errno = ERROR;
        return FALSE;
    }

    if (pos != 0 && tree->len == pos)
    {
        errno = ERROR;
        return FALSE;
    }

    // 新建结点
    TreeNode* node = (TreeNode*) malloc(sizeof(TreeNode)/sizeof(char));
    if (NULL == node)
    {   
        errno = MALLOC_ERROR;
        return FALSE;
    }

    node->data = data;
    node->next = NULL;

    // 创建该新节点的孩子结点链表的头节点
    node->childList = (ChildNode*) malloc(sizeof(ChildNode)/sizeof(char));
    if (NULL == node->childList)
    {   
        errno = MALLOC_ERROR;
        free (node);
        return FALSE;
    }   
    node->childList->next      = NULL;
    node->childList->childNode = NULL;

    node->degree = 0;

    int i;
    // 找父节点
    TreeNode* parent = tree->head->next;     // 当前树节点的第一个结点
    for (i = 0; i < pos; i++)
    {
        parent = parent->next;
    }
    node->parent = parent; 

    // 在父亲结点的子结点链表中加入一个结点
    if (parent != NULL)
    {
        // 创建一个孩子结点
        ChildNode* childnode = (ChildNode*) malloc(sizeof(ChildNode)/sizeof(char));
        if (NULL == childnode)
        {
            errno = MALLOC_ERROR;
            free (node->childList);
            free (node);
            return FALSE;
        }
        childnode->childNode = node;
        childnode->next      = NULL;

        // 加入到父亲结点子结点链表当中
        ChildNode* tmp = parent->childList;   // 子结点链表的头节点
        while (tmp->next)
        {   
            tmp = tmp->next;
        }
        tmp->next = childnode;
        parent->degree += 1;
    }

    TreeNode* tmp = tree->head;              // 树节点链表的头节点
    while (tmp->next)
    {
        tmp = tmp->next;
    }
    tmp->next = node;
    tree->len += 1;

    return TRUE;
}

// 递归打印结点
void r_display (TreeNode* node, int gap, TreePrint pFunc)
{
    if (NULL == node)
    {
        return;
    }

    // 打印距离前一个结点的距离
    int i;
    for (i = 0; i < gap; i++)
    {
        printf ("%c", '-');
    }

    // 打印结点自己
    // printf ("%c\n", node->data);
    pFunc (node);

    ChildNode* child = node->childList->next; // 该结点的第一个孩子
    // 打印该结点的孩子
    while (child)
    {
        r_display (child->childNode, gap+4, pFunc);
        child = child->next;  // 下一个孩子
    }
}

void Display (Tree *tree, TreePrint pFunc)
{
    if (NULL == tree)
    {
        return;
    }

    r_display (tree->head->next, 0, pFunc);
}

void r_delete (Tree *tree, TreeNode *node)
{
    if (NULL == tree || NULL == node)
        return;

    // 从树链表中移除这个结点,找node的前一个结点
    TreeNode* tmp = tree->head;  // 链表的头节点
    while (tmp->next)
    {
        if (tmp->next == node)
        {
            tmp->next = node->next;
            tree->len--;
            break;
        }
        tmp = tmp->next;
    }

    // 将父亲结点中子结点链表中指向node的结点删除
    TreeNode* parent = node->parent;
    if (NULL != parent)
    {
        ChildNode* tmp = parent->childList;  // 子结点链表的头节点
        while (tmp->next)
        {
            if (tmp->next->childNode == node)
            {
                ChildNode* p = tmp->next;
                tmp->next    = p->next;
                free (p);
                parent->degree--;
                break;
            }
            tmp = tmp->next;
        }
    }

    // 将该结点的孩子结点删掉
    ChildNode* child = node->childList->next; 
    // 子结点链表中的第一个结点
    while (child)
    {
        ChildNode* pchild = child->next;
        r_delete (tree, child->childNode);
        child  = pchild;
    }

    free (node->childList);
    free (node);
}

int Delete (Tree *tree, int pos, TreeData *x)
{
    if (NULL == tree || pos < 0 || pos > tree->len)
    {
        errno = ERROR;
        return FALSE;
    }

    if (0 != pos && tree->len == pos)
    {
        errno = ERROR;
        return FALSE;
    }

    int i;
    // 找结点
    TreeNode* current = tree->head->next;  
    for (i = 0; i < pos; i++)
    {
        current = current->next;
    }

    *x = current->data;

    r_delete (tree, current);

    return TRUE;

}

int Tree_Get (Tree* tree, int pos, TreeData *x)
{
    if (NULL == tree || pos < 0 || pos > tree->len)
    {
        errno = ERROR;
        return FALSE;
    }

    if (0 != pos && tree->len == pos)
    {
        errno = ERROR;
        return FALSE;
    }

    int i;
    // 找结点
    TreeNode* current = tree->head->next;  
    for (i = 0; i < pos; i++)
    {
        current = current->next;
    }

    *x = current->data;

    return TRUE;
}

int Tree_Clear (Tree* tree)
{
    if (NULL == tree)
    {
        errno = ERROR;
        return FALSE;
    }

    TreeData x;
    return Delete (tree, 0, &x);
}

void Tree_Destroy (Tree* tree)
{
    if (NULL == tree)
    {
        errno = ERROR;
        return;
    }

    Tree_Clear (tree);

    free (tree->head);
    free (tree);
}

TreeNode* Tree_Root (Tree* tree)
{
    if (NULL == tree)
    {
        errno = ERROR;
        return NULL;
    }

    return tree->head->next;
}

int Tree_Count (Tree* tree)
{
    if (NULL == tree)
    {
        errno = ERROR;
        return FALSE;
    }

    return tree->len;
}

// 递归求高度
int r_height (TreeNode* node)
{
    if (NULL == node)
    {
        return 0;
    }

    int subHeight = 0;
    int max       = 0;
    ChildNode* child = node->childList->next;
    while (child)
    {
        subHeight = r_height (child->childNode);
        if (subHeight > max)
        {
            max = subHeight;
        }
        child = child->next;
    }

    return max + 1;
}

int Tree_Height (Tree* tree)
{
    if (NULL == tree)
    {
        errno = ERROR;
        return FALSE;
    }

    int height = r_height (tree->head->next);

    return height;
}

// 递归求度
int r_degree (TreeNode* node)
{
    if (NULL == node)
    {
        return 0;
    }

    int max       = node->degree;
    int subDegree = 0;
    ChildNode* child = node->childList->next;
    while (child)
    {
        subDegree = r_degree (child->childNode);
        if (subDegree > max)
        {
            max = subDegree;
        }
        child = child->next;
    }

    return max;
}

int Tree_Degree (Tree* tree)
{
    if (NULL == tree)
    {
        errno = ERROR;
        return FALSE;
    }

    int degree = r_degree (tree->head->next);

    return degree;
}

void printA (TreeNode* node)
{
    printf ("%c\n", node->data);
}


主函数 main.c

#include <stdio.h>
#include "tree.h"



int main()
{
    Tree* tree = Create_Tree();
    if (NULL == tree)
    {
        myError ("Create_Tree");
        return -1;
    }

    Insert_Tree (tree, 'A', 0);
    Insert_Tree (tree, 'B', 0);
    Insert_Tree (tree, 'C', 0);
    Insert_Tree (tree, 'D', 0);
    Insert_Tree (tree, 'E', 1);
    Insert_Tree (tree, 'F', 1);
    Insert_Tree (tree, 'H', 3);
    Insert_Tree (tree, 'I', 3);
    Insert_Tree (tree, 'J', 3);
    Insert_Tree (tree, 'X', 3);
    Insert_Tree (tree, 'Z', 8);

    Display (tree, printA);

    //printf ("删除B :\n");
    TreeData x;
    //Delete(tree, 1, &x);
    //Display(tree, printA);

    printf ("height = %d\n", Tree_Height(tree));
    printf ("degree = %d\n", Tree_Degree(tree));
    return 0;
}

error.h是我自己写的一个包含常见错误的头文件,这里我就不发了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值