算法—前缀树(C++实现)

目录

1.前缀树的结点定义

2.前缀树封装的一些方法

2.1创建一个串对应的路2.2word这个单词之前加入过几次2.3在所有加入字符串中,有多少个是以pre作为前缀的2.4删除单词

 

1.前缀树的结点定义

#include<iostream>
#include<string>
#include<unordered_set>
using namespace std;
//前缀树的结点定义
class TrieNode {
public:
	int pass;//在创建的过程中经过的路的次数
	int end;//每条字符串结尾的路的次数
	TrieNode* *nexts;
	TrieNode(){
		pass = 0;
		end = 0;
		*nexts = new TrieNode[26];
	}
	TrieNode(int ps, int en) {
		pass = ps;
		end = en;
		//nexts[0]==NULL表示没有走向‘a'的路
		//nexts[0]!=NULL表示有走向‘a'的路
		//nexts[25]==NULL表示没有走向‘z’的路
		//nexts[25]!=NULL表示没有走向‘z’的路
		*nexts = new TrieNode[26];
	}
};

2.前缀树封装的一些方法

2.1创建一个串对应的路
2.2word这个单词之前加入过几次
2.3在所有加入字符串中,有多少个是以pre作为前缀的
2.4删除单词

class Trie {
private:
	TrieNode* root;//头结点
public:
	Trie(){
		root = new TrieNode;
	}
	//创建一个串对应的路
	void insert(string word) {
		if (word.size()<1)
			return;
		TrieNode* node = root;
		node->pass++;//只要经过就+1
		int index = 0;
		for (char ch : word) {//从左往右遍历字符
			index = ch - 'a';//由字符对应哪条路
			if (node->nexts[index] == NULL)//没有,就新建一个结点
				node->nexts[index] = new TrieNode;
			node = node->nexts[index];
			node->pass++;
		}
		node->end++;
	}
	//word这个单词之前加入过几次
	int search(string word) {
		TrieNode* node = root;
		int index = 0;
		for (char ch : word) {
			index = ch - 'a';
			if (node->nexts[index] == NULL)
				return 0;
			node = node->nexts[index];
		}
		return node->end;
	}
	//在所有加入字符串中,有多少个是以pre作为前缀的
	int prefixNumber(string pre) {
		TrieNode* node = root;
		int index = 0;
		for (char ch : pre) {
			index = ch - 'a';
			if (node->nexts[index] == NULL)
				return 0;
			node = node->nexts[index];
		}
		return node->pass;
	}
	//删除单词
	/*
	step:  1)先检查是否存在单词,存在了再删,否则直接跳过
		   2)将单词路过的字符的pass--,到单词末尾再将end--。
	*/
	void deleteWord(string word) {
		if (search(word) != 0) {//先判断是否存在
			TrieNode* node = root;
			node->pass--;
			int index = 0;
			TrieNode* a = new TrieNode;
			int deleteIndex = -1;
			unordered_set< TrieNode*>deleteSet;
			for (int i = 0;i<word.size();i++) {
				index = word[i] - 'a';
				//如果pass为0了,就将头结点记录一下,放在表中,最后释放
				if (--node->nexts[index]->pass == 0) {
					//如果为不为空就说明之前已经设置过了,就直接用原来的值就行
					a = a == NULL ? node : a;
					deleteIndex = deleteIndex == -1 ? index : deleteIndex;
					deleteSet.insert(node->nexts[index]);
				}
				node = node->nexts[index];
			}
			node->end--;
			a->nexts[deleteIndex] = NULL;
			//析构释放
			for (TrieNode* dele : deleteSet) {
				delete dele;
				dele = NULL;
			}
		}
	}
}; 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值