字典树

15 篇文章 0 订阅
4 篇文章 0 订阅

字典树在这里插入图片描述

字典树是一种数据结构,用于处理大量字符串。优点在于利用字符串的公共前缀,在存储时节约存储空间,并在查询时最大限度的减少无谓的字符串比较。
字典树主要包含以下功能:

  1. 插入结点(建树)
  2. 查找/匹配

本文的代码实现上包含:建树,查找单词,关键词查找,释放内存。
以动态分配为实现字典树,与网上代码不同的是根据思考,加入了关键词查找:
创建大小为26的Ptr结构体数组来储存字母地址,寻找关键词就等同于从字典树的子树出发匹配,而非根节点。

输入:aba,bab,bba,cab
关键词:ba
输出:aba,bab,bba
在这里插入图片描述
关键词:ab
输出:aba,bab,cab
在这里插入图片描述
具体代码:

#include <iostream>
#include <cstdio>
#include <stack>
#include <queue>
#include <string>
#include <regex>
using namespace std;

const regex pattern("^[a-zA-Z]+$");
//match_results<string::const_iterator> result;

struct Node
{
	Node *next = nullptr;
	Node *down = nullptr;
	Node *up = nullptr;
	char ch;
	bool flag = 0;
};

struct Ptr
{
	Node *p = nullptr;
	Ptr *next = nullptr;
};
class Trie
{
private:
	Ptr array[26];	//快查
	Node *head;			//头结点

	
	//判断是否存在单词
	Node* Exist(Node *temp, const char ch, const bool flag = true)	
	{
		while (temp->next != nullptr && temp->ch != ch) {
			temp = temp->next;
		}
		if (temp->ch == ch) {
			return temp;
		}
		else if (flag) {
			return Create(temp, ch);
		}
		else{
			return nullptr;
		}
	}

	//判断并储存地址
	void ptr_Exist(Ptr *q ,Node *temp)
	{
		while (q->next != nullptr)
		{
			if (q->p == temp) { break; }
			q = q->next;
		}
		if (q->p != temp) {
			q->next = Create(temp);
		}
	}

	//添加结点
	Node *Create(Node *temp, const char ch, const bool flag = true)
	{
		Node *newNode = new Node;
		newNode->ch = ch;
		if (flag) {
			temp->next = newNode;
		}
		else {
			temp->down = newNode;
		}
		return newNode;
	}
	Ptr *Create(Node *temp)
	{
		Ptr *newPtr = new Ptr;
		newPtr->p = temp;
		return newPtr;
	}

	//搜索关键字
	bool searchKeywords(const string &str, Node *pNode)
	{
		Node *root = pNode;
		Node *temp;
		for (int i = 1; i < str.length(); i++)
		{
			if (root->down == nullptr) { return false; }
			temp = Exist(root->down, str[i], false);
			if (temp == nullptr) { return false; }
			root = temp;
		}
		temp = root;
		stack<char> up;
		queue<char> down;
		while (temp->up != nullptr)
		{
			up.push(temp->ch);
			temp = temp->up;
		}
		bfs(up, root->down, down);
		return true;
	}


	//打印
	void print(stack<char> up, queue<char> down)
	{
		while (!up.empty()) {
			printf("%c", up.top());
			up.pop();
		}
		while (!down.empty()) {
			printf("%c", down.front());
			down.pop();
		}
		printf("\n");
	}
	void bfs(stack<char> up, Node *temp, queue<char> down)
	{
		if (temp != nullptr) {
			if (temp->next != nullptr) {
				bfs(up, temp->next, down);
			}
			down.push(temp->ch);
			if (temp->flag == 1 && temp->down != nullptr) {
				print(up, down);
			}
			bfs(up, temp->down, down);
		}
		else {
			print(up, down);
		}
	}
	
	//释放
	void Realse(Node *temp)	
	{
		if (temp == nullptr) { return; }
		if (temp != nullptr)
		{
			Realse(temp->down);
			temp->down = nullptr;
			Realse(temp->next);
			temp->next = nullptr;
		}
		delete temp;
		temp = nullptr;
	}
	void Realse(Ptr *temp)
	{
		if (temp != nullptr)
		{
			Realse(temp->next);
			temp->next = nullptr;
			temp->p = nullptr;
		}
		delete temp;
		temp = nullptr;
	}

public:
	//构造
	Trie(){	head = new Node;}

	//析构
	~Trie(){ Realse(head);}

	//清空字典树
	void clean()
	{
		Realse(head->down);
		head->down = nullptr;
		for (int i = 0; i < 26; ++i)
		{
			Realse((array + i)->next);
			array[i].next = nullptr;
		}
	}

	//增加单词
	void insert(const string &str)
	{
		Node *root = head;
		Node *temp;
		for (int i = 0; i < str.length(); i++)
		{
			if (root->down == nullptr) {
				temp = Create(root, str[i], false);
			}
			else {
				temp = Exist(root->down, str[i]);
			}
			temp->up = root;
			root = temp;
			ptr_Exist((array + str[i] - 'a'), temp);
		}
		root->flag = 1;
	}

	//查找单词
	bool search(const string &str)
	{
		Node *root = head;
		Node *temp = nullptr;
		for (int i = 0; i < str.length(); i++)
		{
			if (root->down == nullptr) {
				return false;
			}
			else {
				temp = Exist(root->down, str[i], false);
			}
			root = temp;
		}
		if (temp == nullptr){
			return false;
		}
		if (root->flag == 1) {
			return true;
		}
		else {
			return false;
		}
	}

	//关键词查找
	bool search_keywords(const string &str)
	{
		bool flag = false;
		Ptr *q = (array + str[0] - 'a')->next;
		while (q != nullptr)
		{
			if (searchKeywords(str, q->p))
				flag = 1;
			q = q->next;
		}
		return flag;
	}

};


int main()
{
	Trie *trie = new Trie();
	printf("1.清空字典树\n2.增加单词\n3.查找单词\n4.关键词查找...\n");
	int cmd;
	while (cin >> cmd, cmd)
	{
		if (cmd == 1){
			trie->clean();
		}
		else if (cmd == 2)
		{
			string str;
			printf("退出插入单词模式请输入0回车...\n");
			while (cin >> str, str.compare("0") != 0)
			{
				//if (regex_match(str, result, pattern))
				if (regex_match(str, pattern))
				{
					transform(str.begin(), str.end(), str.begin(), ::tolower);
					trie->insert(str);
				}
				else{ break;}
			}
		}
		else if (cmd == 3)
		{
			string str;
			printf("输入你想查找的单词...\n");
			cin >> str;
			if (!regex_match(str, pattern)) {
				printf("输入的不是英文...\n");
			}
			else
			{
				transform(str.begin(), str.end(), str.begin(), ::tolower);
				if (!trie->search(str)) {
					printf("很抱歉!没有找到这个单词...\n");
				}
				else {
					printf("找到啦!\n");
				}
			}
		}
		else if (cmd == 4)
		{
			string str;
			printf("输入你想查找的关键字...\n");
			cin >> str;
			if (!regex_match(str, pattern)) {
				printf("输入的不是英文...\n");
			}
			else
			{
				transform(str.begin(), str.end(), str.begin(), ::tolower);
				if (!trie->search_keywords(str)) {
					printf("很抱歉!没有找到任何含有此关键字的单词...\n");
				}
			}
		}
		else{
			printf("无效指令...\n");
		}
		printf("1.清空字典树\n2.增加单词\n3.查找单词\n4.关键词查找...\n");
	}
	delete trie;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值