1. 程式人生 > >資料結構之樹的一些基本操作

資料結構之樹的一些基本操作

是由根結點和若干顆子樹構成的。樹是由一個集合以及在該集合上定義的一種關係構成的。集合中的元素稱為樹的結點,所定義的關係稱為父子關係。父子關係在樹的結點之間建立了一個層次結構。在這種層次結構中有一個結點具有特殊的地位,這個結點稱為該樹的根結點,或稱為樹根。
標頭檔案 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是我自己寫的一個包含常見錯誤的標頭檔案,這裡我就不發了。