CLRS 思考题 12-2 利用字典树处理字符串排序

Description


 

  给定两个串a = 'a0a1……ap'和b = 'b0b1……bq',其中每一个 ai 和每一个 bj 都属于某个有序字符集,如果下面两条规则之一成立,则说串a按字典序小于串b: 

     1)存在一个整数 j,0 <= j <= min(p,q),使得ai = bi,i = 0,1,……,j-1,且aj < bj; 

    2)p < q,且ai = bi,对所有的i = 0,1,……,p 成立 

  例如,如果a和b是位串,则根据规则1)(设j=3),有10100 < 10110;根据规则2),有10100 < 101000。这与英语字典中的排序很相似。

  下图显示的是基数树(radix tree)数据结构,其中存储了位串1011、10、011、100和0。当查找某个关键字a = a0a1……ap时,在深度为i的一个结点处,若ai = 0则向左转;若ai = 1则向右转。设S为一组不同的二进制串构成的集合,各串的长度之和为n。说明如何利用基数树,在O(n)时间内对S按字典序排序。例如,对图12-5中每个结点的关键字,排序的输出应该是序列0、011、10、100、1011

          

 

思路


 

  大量字符串统计问题通常都是用 trie 树 or 哈希表,但是 哈希表排序的话 O(n) 有点难,所以选择 trie 树。

  从题目的 hint 中很容易知道用 trie 树 + 前序遍历即可实现字典排序。其中 insert 的时间为 O(n),print 的时间为 O(n),所以算法的时间复杂度为 O(n)

   在ASCLL码与字符的问题上 WA 了一发,C++ 没有数组边界检查导致查了很久,下次建 trie 树需要多多注意这个点。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

//利用trie存储位串
struct Node{
    Node *next[2]; //一个结点的next结点有两种可能
    bool flag;
    string str;
    int cnt;
    Node() {
        for (int i = 0; i <2; i++) next[i] = NULL;
        flag = false;
        str = "";
        cnt = 0;
    }
};
Node *root;

void initTrie(){
    root = new Node();
}

void insert(const string& s){
    int len = s.size();
    Node *now = root;

    for (int i = 0; i < len; i++) {
        int to = s[i] - '0'; //需要依据ASCLL码做减法,否则隐式转换to将等于48/49
        if (!now->next[to]) now->next[to] = new Node();
        now = now->next[to];
    }
    if (now->flag) {
        ++now->cnt;
        return;
    }
    else {
        now->flag = true;
        now->str = s;
        now->cnt = 1;
    }
}

void preOderPrint (Node *now) {
    if (!now) return;
    if(now->flag) {
        for (int i = 0; i < now->cnt; i++)
            cout << now->str << endl;
    }
    preOderPrint(now->next[0]);
    preOderPrint(now->next[1]);
}

int main(void) {
    initTrie();
    string tmp = "";
    while(cin >> tmp) {
        insert(tmp);
    }
    preOderPrint(root);
    return 0;
}
View Code

 

  

posted @ 2018-03-08 16:43  bw98  阅读(410)  评论(0编辑  收藏  举报