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