1. 程式人生 > >Trie tree(字典樹)

Trie tree(字典樹)

pri table main radix gcc編譯器 out 字典 name dia

  Trie tree有時被稱為(digital tree)或(radix tree or prefix tree)。

  可能是編譯器問題,我的實現方法用gcc編譯器,debug沒問題,但一run就有問題。。。

  Debug output:

Starting debugger: C:\TDM-GCC-64\bin\gdb.exe -nx -fullname -quiet  -args E:/CodeBlocks_C++Projects/NYOJ/bin/Debug/NYOJ.exe
done
Setting breakpoints
Debugger name and version: GNU gdb (GDB) 7.9.1
Child process PID: 208
[Inferior 1 (process 208) exited normally]
Debugger finished with status 0

  弄了很久,還以為是我哪裏指針處理沒做好,但最後不管怎麽想都覺得邏輯都沒問題,於是換VS,run成功了,而且結果是正確的。

  原理很簡單,沒什麽好說的,看wiki上的圖就能夠明白什麽是前綴樹,以及如何設計這樣的數據結構了。遍歷的思路用的是二叉樹的後序遍歷思想,這裏用循環建立了26個子遞歸,實際上原理是一樣的。ps:其實成員letter沒有必要有。。。

  code:

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 26
#define INDEX(c) ((c) - ‘a‘)
#define ARR_SIZE(strs) (sizeof((strs))/sizeof(strs[0]))

#define FOR(i, range, node) for (i = 0; i < range; i++) node->children[i] = NULL

typedef struct BaseNode {
	struct BaseNode* children[SIZE];
	char letter;
	char*s;
}trie;

trie*init()
{
	int i;
	trie*root = (trie*)malloc(sizeof(trie));
	root->letter = 0;
	FOR(i, SIZE, root);
	root->s = NULL;
	return root;
}

trie*insert(trie*root, char str[])
{
	trie*node = root;
	int i, j;
	for (i = 0; node->children[INDEX(str[i])] != NULL; i++)
	{
		node = node->children[INDEX(str[i])];
	}
	while (i < (int)strlen(str))
	{
		trie*temp = (trie*)malloc(sizeof(trie));
		temp->letter = str[i];
		FOR(j, SIZE, temp);
		temp->s = NULL;
		if (i + 1 == (int)strlen(str))
			temp->s = str;
		node->children[INDEX(str[i])] = temp;
		node = temp;
		i++;
	}
	FOR(j, SIZE, node);
	return root;
}

trie*search(trie*root, char str[])
{
	trie*node = root;
	for (int i = 0; i < (int)strlen(str); i++)
	{
		if (node != NULL)
		{
			node = node->children[INDEX(str[i])];
			// printf("%c -> ", node->letter);
		}
		else
			break;
	}
	return node;
}

bool remove_helper(trie*node)
{
	for (int i = 0; i < SIZE; i++)
	{
		if (node->children[i] != NULL)
			return true;
	}
	return false;
}

void remove(trie**node, char*str)
{
	if (*node != NULL)
	{
		char c = *str;
		++str;
		remove(&(*node)->children[INDEX(c)], str);
		if (!remove_helper(*node))
		{
			free(*node);
			*node = NULL;
		}
	}
}

void show(trie*node)
{
	if (node != NULL)
	{
		for (int i = 0; i < SIZE; i++)
		{
			show(node->children[i]);
		}
		printf("%s\n", node->s);
	}
}

void destory(trie*node)
{
	if (node != NULL)
	{
		for (int i = 0; i < SIZE; i++)
		{
			destory(node->children[i]);
		}
		free(node);
		node = NULL;
	}
}

int main()
{
	char strs[][12] = { "tea","eat","engineer","table","profile" };
	trie*root;

	root = init();

	for (int i = 0; i < (int)ARR_SIZE(strs); i++)
	{
		root = insert(root, strs[i]);
	}

	show(root);
	remove(&root, strs[0]);
	// trie*node = search(root, strs[0]);
	show(root);
	destory(root);
	getchar();
	return 0;
}

  Output:

eat
engineer
profile
table
tea
(null)
(null)
(null)
eat
engineer
profile
table

  參考:

    https://github.com/darkchii/cosmos/blob/master/code/data_structures/src/tree/tree/trie/trie.c

    https://en.wikipedia.org/wiki/Trie

Trie tree(字典樹)