数据结构--孩子双亲表示法存储树结构之静态链式存储(C风格的C++)

孩子双亲表示法:

     

插入:        

        孩子双亲表示法的主要思想是将每个节点的孩子排列起来看成是一个线性表,且以单链表作为存储结构。首先将元素保存到一个数组里面(结合双亲表示法),然后里面要保存双亲信息,接着就是将每个元素找到它的孩子,将孩子插入到孩子链表中,根据双亲信息找到每个节点的孩子,将孩子节点添加到每个节点的child域,这样就完成了插入工作。

//插入
PTree *Insert(PTree *tree, ElemType data, int pos) {
    if (tree->size == tree->n) {
        cout << "The tree is full!";
        return nullptr;
    }
    auto *code = new TreeCode;
    code->data = data;
    code->parent = pos;
    code->child = nullptr;  // 初始化孩子链表为空

    tree->nodes[tree->size] = *code;  // 将新的节点插入到树中

    // 找到父节点,并将新节点插入到父节点的孩子链表中
    for (int i = 0; i < tree->size; i++) {
        if (i == pos) {
            auto parent = &tree->nodes[i];
            if (parent->child == nullptr) {
                parent->child = code;
            } else {
                auto p = parent->child;
                while (p->child != nullptr) {
                    p = p->child;
                }
                p->child = code;
            }
            break;
        }
    }

    tree->size++;
    return tree;
}

删除:

        接下来是删除,要想删除一个元素,首先要将要删除的元素找到,首先删除数组中的数据,接着要找到该元素的双亲节点,遍历该双亲节点的孩子链表,将孩子链表中的数据删除,并释放内存空间,防止内存泄漏。

//删除
void del(PTree* tree,ElemType data){
    for(int i=0;i<tree->size;i++){
        if (tree->nodes[i].data==data){
            cout<<"删除的元素为:"<<tree->nodes[i].data<<","<<tree->nodes[i].parent<<endl;
            for(int j=i;j<tree->size-1;j++) {
                tree->nodes[i] = tree->nodes[j + 1];

                //遍历孩子链表,找到父节点,将指向该孩子的节点删除
                for(int index = 0; index < tree->size; index++) {
                    auto parent = &tree->nodes[index];
                    auto p = parent->child;
                    while(p != nullptr){
                        if (p == &tree->nodes[i]){
                            parent->child = p->child;
                            delete p;
                            break;
                        }
                        p = p->child;
                    }
                }
            }
        }
    }
    tree->size--;
}

释放内存:

        释放内存,首先要找到叶子节点,即遍历孩子链表,找到孩子节点,将其释放,接着一级一级释放,直至遍历完全部元素。

//释放内存
PTree* Free(PTree* tree) {
    int i = 0;
    while (i < tree->size) {
        if (tree->nodes[i].child == nullptr) {
            // 找到叶子节点,删除该节点并更新父节点的孩子链表
            auto parent = tree->nodes[i].parent;
            auto p = tree->nodes[parent].child;
            if (p == &tree->nodes[i]) {
                tree->nodes[parent].child = nullptr;
            } else {
                while (p->child != &tree->nodes[i]) {
                    p = p->child;
                }
                p->child = nullptr;
            }
            delete &tree->nodes[i];
            i++;
        } else {
            // 找到非叶子节点,继续遍历其孩子节点
            i = tree->size;
            auto p = tree->nodes[i].child;
            while (p != nullptr) {
                i--;
                p = p->child;
            }
        }
    }
    return nullptr;
}

访问:

        要想访问该树,即访问存储数据中的数组元素即可。

//访问
void Visit(PTree* tree){
    if (tree->size==0){
        cout<<"The tree is empty!";
    }
    cout<<"Tree Code:"<<endl;
    for (int i=0;i<tree->size;i++){
        cout<<tree->nodes[i].data<<","<<tree->nodes[i].parent<<endl;
    }
}

最后是完整代码:

//孩子双亲表示法
#include<iostream>

#define MAXSIZE 100

using namespace std;

typedef char ElemType;


typedef struct TreeCode{
    ElemType data;
    int parent;
    TreeCode *child;
}Treecode;

typedef struct {
    Treecode nodes[MAXSIZE];
    int size,n;
}PTree;

//初始化
PTree* Init(PTree *tree, ElemType data) {
    tree->size = 1;
    tree->n = MAXSIZE - 1;
    tree->nodes[0].data = data;
    tree->nodes[0].parent = -1;
    tree->nodes[0].child = nullptr;
    return tree;
}

//插入
PTree *Insert(PTree *tree, ElemType data, int pos) {
    if (tree->size == tree->n) {
        cout << "The tree is full!";
        return nullptr;
    }
    auto *code = new TreeCode;
    code->data = data;
    code->parent = pos;
    code->child = nullptr;  // 初始化孩子链表为空

    tree->nodes[tree->size] = *code;  // 将新的节点插入到树中

    // 找到父节点,并将新节点插入到父节点的孩子链表中
    for (int i = 0; i < tree->size; i++) {
        if (i == pos) {
            auto parent = &tree->nodes[i];
            if (parent->child == nullptr) {
                parent->child = code;
            } else {
                auto p = parent->child;
                while (p->child != nullptr) {
                    p = p->child;
                }
                p->child = code;
            }
            break;
        }
    }

    tree->size++;
    return tree;
}

//访问
void Visit(PTree* tree){
    if (tree->size==0){
        cout<<"The tree is empty!";
    }
    cout<<"Tree Code:"<<endl;
    for (int i=0;i<tree->size;i++){
        cout<<tree->nodes[i].data<<","<<tree->nodes[i].parent<<endl;
    }
}

//释放内存
PTree* Free(PTree* tree) {
    int i = 0;
    while (i < tree->size) {
        if (tree->nodes[i].child == nullptr) {
            // 找到叶子节点,删除该节点并更新父节点的孩子链表
            auto parent = tree->nodes[i].parent;
            auto p = tree->nodes[parent].child;
            if (p == &tree->nodes[i]) {
                tree->nodes[parent].child = nullptr;
            } else {
                while (p->child != &tree->nodes[i]) {
                    p = p->child;
                }
                p->child = nullptr;
            }
            delete &tree->nodes[i];
            i++;
        } else {
            // 找到非叶子节点,继续遍历其孩子节点
            i = tree->size;
            auto p = tree->nodes[i].child;
            while (p != nullptr) {
                i--;
                p = p->child;
            }
        }
    }
    return nullptr;
}


//删除
void del(PTree* tree,ElemType data){
    for(int i=0;i<tree->size;i++){
        if (tree->nodes[i].data==data){
            cout<<"删除的元素为:"<<tree->nodes[i].data<<","<<tree->nodes[i].parent<<endl;
            for(int j=i;j<tree->size-1;j++) {
                tree->nodes[i] = tree->nodes[j + 1];

                //遍历孩子链表,找到父节点,将指向该孩子的节点删除
                for(int index = 0; index < tree->size; index++) {
                    auto parent = &tree->nodes[index];
                    auto p = parent->child;
                    while(p != nullptr){
                        if (p == &tree->nodes[i]){
                            parent->child = p->child;
                            delete p;
                            break;
                        }
                        p = p->child;
                    }
                }
            }
        }
    }
    tree->size--;
}



int main(){
    PTree tree;
    Init(&tree, 'A');
    Insert(&tree, 'B', 0);
    Insert(&tree, 'C', 0);
    Insert(&tree, 'D', 1);
    Insert(&tree, 'F', 2);
    Insert(&tree, 'R', 3);
    Insert(&tree,'b',0);
    del(&tree,'C');
    del(&tree,'R');
    del(&tree,'D');
    Visit(&tree);
    Free(&tree);

    return 0;
}

简单的运行一下:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值