孩子双亲表示法:
插入:
孩子双亲表示法的主要思想是将每个节点的孩子排列起来看成是一个线性表,且以单链表作为存储结构。首先将元素保存到一个数组里面(结合双亲表示法),然后里面要保存双亲信息,接着就是将每个元素找到它的孩子,将孩子插入到孩子链表中,根据双亲信息找到每个节点的孩子,将孩子节点添加到每个节点的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;
}
简单的运行一下: