您的位置:首页 > 其它

算法第四版5-2Tries_Trees

2016-10-11 23:39 281 查看
#include
#include
#include
using namespace std;
#define alphabet_size 256
//C++嵌套类
//1.嵌套类的名字只在外围类可见。
//2.类的私有成员只有类的成员和友元可以访问,因此外围类不可以访问嵌套类的私有成员。嵌套类可以访问外围类的成员(通过对象、指针或者引用)。
//3.一个好的嵌套类设计:嵌套类应该设成私有。嵌套类的成员和方法可以设为 public 。
//4.嵌套类可以直接访问外围类的静态成员、类型名( typedef )、枚举值。
class trie {
const  static int R = alphabet_size;
class node {
public:
int val;
node* next[R];
node() {
for (int i = 0; i < R; i++) next[i] = NULL;
val = NULL;
}
node(int v) {
val = v;
for (int i = 0; i < R; i++) next[i] = NULL;
}
};
node* root;
public:
trie() {
root = NULL;
}
void put(string s, int v) {
root = put(root, s, v, 0);
}
node* put(node* x, string s, int v, int d) {
if (x == NULL) x = new node();
if (d == s.length()) {
x->val = v;
return x;
}
char temp = s.at(d);
x->next[temp] = put(x->next[(int)temp], s, v, d + 1);
return x;
}
int get(string s) {
node* temp = get(root, s, 0);
if (temp == NULL) {
perror("Invalid");
return NULL;
}
return temp->val;
}
node* get(node* x, string s, int d) {
if (x == NULL) return NULL;
if (d == s.length()) return x;
char temp = s.at(d);
return get(x->next[temp], s, d + 1);
}
queue keywithprefix(string pre) {   //find all keys that start from p
queue res;     // use queue to record the key with prefix
collect(get(root, pre, 0), pre, res);
return res;
}
void collect(node* x, string p, queue &q) {
if (x == NULL) return;
//cout << p << endl;   //调试递归调用,加栈标识符
if (x->val != NULL) {
q.push(p);
}
for (int i = 0; i < R; i++) {  // char 为-128到128,有负值,不能作为index;改用unsigned char或者int,使用(char)转换为char
/*if ((int)i == 111||(int)i==101||(int)i==255) {
system("pause");
}*/
//cout << (int)i << endl;   // 调试循环,输出标识,记录进入函数时的i值
collect(x->next[i], p + (char)i, q);   // check everyone but enqueue the certain ones
}
}
queue keythatmatch(string pat) {   //find all keys that exactly match pat
queue res;
collect(root, "", pat, res);
return res;
}
void collect(node* x, string p, string pat, queue &q) {   //use p to record the paths
if (x == NULL) return;
int d = p.length();   //use string length as the signal of end recurrence
if (d == pat.length() && x->val != NULL) q.push(p);   //all match and the key is valid(x->val!=NULL)
if (d == pat.length()) return;   //end match or not match
for (int i = 0; i < R; i++) {
if (pat.at(d) == '.' || i == pat.at(d)) {  //单引号为char,双引号为字符串(const char*),结尾有\0 ; string.at(d)为char类型单字符,不能和双引号比较
collect(x->next[i], p + (char)i, pat, q);
}
}
}
string longestprefix(string s) {
int len = search(root, s, 0, 0);
return s.substr(0, len);
}
// d for the current seacrhing index,len save the length of the matched valid key,not index
int search(node* x, string s, int d, int len) {
if (x == NULL) return len;
if (x->val != NULL) len = d;   //in the first recur,d=0,x=root,has 0 letter,so length is 0
//in the second recur,d=1,x=root->next[i],has one letter,if match,length=1
//in the last,eg,d=n,x=last_letter,has all string,so length=n
if (d == s.length()) return len;
return search(x->next[s.at(d)], s, d + 1, len);
//in the last case,d=n-1,s.at[d] refer the last letter(valid),d+1=s.length(),if match,len=s.length() (valid)
}
void del(string s) {
root = del(root, s, 0);
}
//just set val=NULL,not delete the node ,unless all node->next=NULL
node* del(node* x, string s, int d) {
if (x == NULL) {
perror("valid key");
return root;
}
if (d == s.length()) x->val = NULL;
else {
x->next[s.at(d)] = del(x->next[s.at(d)], s, d + 1);
//return the deleted node*,if NULL,set next[x] NULL,or update next[x]
//assign to x->next[] to update itself,commonly used in recur_delete operation
}
// !!!
if (x->val != NULL) return x;
//avoid delete node with same prefix but has value,eg delete shell-1,avoid delete she-5
//prevent delete the prefix has value but no other subtree,it's next array is all NULL excepet the delete one
for (int i = 0; i < R; i++) {
if (x->next[i] != NULL) return x;   //if all next[] is NULL,return NULL,to set pa's next[this]=NULL
}
return NULL;
}
};
int main() {
int a, n;
string s;
trie t;
queue q;
while (true) {
cin >> n;
while (n--) {
cin >> s >> a;
t.put(s, a);
}
cin >> s;
cout << t.get(s) << endl;
cin >> s;

q = t.keywithprefix(s);
while (!q.empty()) {
cout << q.front() << endl;
q.pop();
}
cin >> s;
q = t.keythatmatch(s);
while (!q.empty()) {
cout << q.front() << endl;
q.pop();
}
cin >> s;
cout << t.longestprefix(s) << endl;
cin >> s;
t.del(s);
cout << t.longestprefix(s) << endl;
}
return 0;
}

Algorithm 5-2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: