动态建树和静态建树 理解
前言
Trie树理解,该博客已经对Trie树进行了简要的介绍;
Trie树分为静态建树和动态建树,两者的区别在于:
- 插入操作时,静态建树中插入不存在的结点利用的是已经创建好的大数组进行存放,而动态数组则会动态申请一个结点;
- 删除操作时,静态建树中删除只需将跟节点的next数组都置为空即可,而动态建树中则要递归删除已经分配的每一个结点;
- 动态建树使用new费时,静态建树预存结点数据很费空间;
静态建树
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 数组个数
#define Max 10000
struct Tree_Node {
bool end;
int count; //记录访问某个字符串的个数
struct Tree_Node * next[26];
}node[Max];
typedef struct Tree_Node * Node;
// 输入字符串
char input[12];
// 静态建树的特点,记录用了几个Node,则下一个结点是node[move]
int move = 0;
void insert_heap(Node root) {
Node pNode = root;
char * tmp = input;
while (*tmp != '\0') {
int idx = *tmp - 'a';
if (!pNode->next[idx]) {
pNode->next[idx] = &node[move++];
pNode->next[idx]->end = false;
pNode->next[idx]->count = 0;
memset(pNode->next[idx]->next, 0, sizeof(pNode->next[idx]->next));
}
tmp++;
pNode = pNode->next[idx];
}
//访问结束
pNode->end = true;
pNode->count++;
}
void build_heap(Node root) {
for (int i = 0; i < 12; ++i) {
scanf("%s", input);
insert_heap(root);
}
}
void search_heap(Node root) {
char *tmp = input;
Node pNode = root;
while (*tmp != '\0') {
int idx = *tmp - 'a';
if (!pNode->next[idx])
break;
tmp++;
pNode = pNode->next[idx];
}
if (*tmp != '\0' || !pNode->end) {
printf("no exist\n");
}
else {
printf("exist count :%d\n", pNode->count);
}
}
void delete_heap(Node root) {
memset(root->next, 0, sizeof(root->next));
}
int main(int argc, const char * argv[]) {
// insert code here...
Node root = &node[move++];
memset(root->next, 0, sizeof(root->next));
printf("input content\n");
build_heap(root);
printf("get the result\n");
for (int i = 0; i < 12; ++i) {
scanf("%s", input);
search_heap(root);
}
delete_heap(root);
return 0;
}
这里需要注意的地方在于全局维护一个move下标,增加新结点时要移动到下一位;
动态建树
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 1000000
typedef struct Tree_Node {
int count; //记录访问某个字符串的个数
struct Tree_Node * next[26];
}TNode,*Node;
// 输入字符串
char input[20];
char output[20];
void insert_heap(Node root) {
Node pNode = root;
char * in = input;
while (*in != '\0') {
int idx = *in - 'a';
if (pNode->next[idx]) {
pNode = pNode->next[idx];
}
else {
pNode->next[idx] = (Node)malloc(sizeof(TNode));
if (!pNode->next[idx]) {
printf("idx %d为空", idx);
}
for (int i = 0; i < 26; ++i) {
pNode->next[idx]->next[i] = NULL;
}
pNode->next[idx]->count = 0;
pNode = pNode->next[idx];
}
in++;
}
//访问结束
pNode->count++;
}
void build_heap(Node root) {
for (int i = 0; i < 4; ++i) {
scanf("%s", input);
insert_heap(root);
}
}
void search_heap(Node root) {
char *tmp = output;
Node pNode = root;
while (*tmp != '\0') {
int idx = *tmp - 'a';
if (!pNode->next[idx])
break;
tmp++;
pNode = pNode->next[idx];
}
if (*tmp != '\0' && pNode->count > 0) {
printf("no exist\n");
}
else {
printf("exist count :%d\n", pNode->count);
}
}
// 释放子结点后,释放跟节点
void delete_heap(Node node) {
for (int i = 0; i < 26; ++i) {
if (node->next[i]) {
delete_heap(node->next[i]);
}
}
free(node);
}
int main(int argc, const char * argv[]) {
Node root = (Node)malloc(sizeof(TNode));
for (int i = 0; i < 26; ++i) {
root->next[i] = NULL;
}
root->count = 0;
printf("input content\n");
build_heap(root);
printf("get the result\n");
scanf("%s", output);
search_heap(root);
delete_heap(root);
return 0;
}
这里需要注意的地方是,分配内存的时候不要弄成指针了,分配的应该是结构的内存大小;
关注公众号:数据结构与算法那些事儿,每天一篇数据结构与算法