符号表及其三种实现1:链表,有序数组

在通过第二章的方法将数据排序之后,我们常常需要进行查找操作,本章就来介绍查找的方法。我们会使用符号表这个词来表示一张抽象的表格,其实就可以把它看成键值对,而键值对就是字典,键对应单词,值对应单词的意思,发音等。

我们先列出符号表symbol table的API:

然后我们的工作就是选择适当的数据结构去实现它,你可以看到,不同的数据结构对效率的影响有多大

无序链表实现符号表

一个简单选择是链表,每个节点存储一个键值对,具体实现看代码:

class SequentialSearchST{
private:
    Node first; //链表首节点
    class Node{
        Key key;
        Value val; //泛型
        Node next;
    public:
        Node(Key key, Value, val, Node next){
            this.key = key;
            this.val = val;
            this.next = next;
        }
    };

public:
    //查找给定的键,返回相关联的值
    Value get(Key key){
        for(Node x = first; x!= NULL; x = x.next){
            if(key==x.key){
                return x.val;
            }
        }
        return NULL;
    }

    //插入给定的键,若存在则更新val
    void put(Key key, Value val){
        for(Node x = first; x!= NULL; x = x.next){
            if(key == x.key){
                x.val = val;
                return;
            }
        }
        //如果没找到,就头插该节点
        first = new Node(key, val, first);
    }
};

有一个很好的地方在于,put没找到值插入时很方便,直接头插,但无论是put还是get,都需要遍历整个链表,都是O(n)的复杂度,不够快,

有序数组实现符号表

它使用的数据结构是一对平行的数据,一个存储键一个存储值(这种技巧在很多算法题也经常可以用)
因为我们一直保持键的有序性,所以在接下来的代码中,你可以看到我们多次利用rank函数,它返回表中小于给定键的键的数量

class BinarySearchST
{
    vector<Key> keys;
    vector<value> val;
    int N;

public:
    int size(){ return N; }

    //后面实现,先假设它实现了
    int rank(Key key);

    Value get(Key key){
        if(isEmpty()) return NULL;
        int i = rank(key);
        if(i<N && keys[i] == key) return vals[i]; //找到了
        else return NULL;
    }

    void put(Key key, Value val){
        int i = rank(key);
        //找到就更新val
        if(i<N && keys[i] == key) {vals[i]=val; return;}
        //如果没找到就要插入,插入的话就要让i-N的元素后移来腾位置
        for(int j=N; j>i; j--){
            keys[i] = keys[i-1];
            vals[j] = vals[j-1];
        }
        keys[i] = key; vals[i] = val;
        N++;

    }
};
//就是个二分查找
int BinarySearchST::rank(Key key){
    int lo = 0, hi = N-1;
    while(lo<=hi){
        int mid = lo + (hi-lo)/2;
        if(key<keys[mid]) hi= mid-1;
        else if(key>keys[mid]) lo = mid+1;
        else return mid;
    }
    return lo;
}
//问一个小问题,如果查找的元素不在符号表中,返回的数字还是小于该键的数量吗?
//答案:是的,不清楚的可以看下图


这个数据结构通过维持键数组的有序性,再通过二分查找,使得get复杂度下降到O(logN),但是还有一点不好,就是插入的时候要腾位置,复杂度还是O(logN)

全部评论

相关推荐

02-11 17:51
腾讯_TEG_技术
点赞 评论 收藏
分享
黑皮白袜臭脚体育生:春节刚过就开卷吗?哈基馆,你这家伙......
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务