一道简单题目的数据结构算法分析

 问题描述:一个保存有阿拉伯数字与字母的字符串,存在重复的字符,用以下哪一种容器可以最快的统计出每个字符出现的次数?
A vector B set C map D hashtable
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;

int hash(int element)
{
    return element;
}
int hash(char element)
{
    return element;
}
template<class Object>
class HashTable
{
public:
    explicit HashTable(int size = 101):theSize(0),theVector(size)
    {
        makeEmpty();
    }
    bool contains(const Object& orig)const;
    bool remove(const Object& orig);
    bool insert(const Object& orig);
    void makeEmpty();
    void printTable()const;
    enum Status
    {EMPTY,ACTIVE,DELETED}; //描述元素状态
private:
    struct hashObject        //结点
    {
        Object element;
        Status eleStatus;
        unsigned int account;    //统计元素个数
    };
    vector<hashObject> theVector;
    int theSize;
    int myHash(const Object& orig)const;
    int findPos(const Object& orig)const;
    bool isActive(int currentPos)const;
};
template<class Object>
void HashTable<Object>::makeEmpty()
{
    for(size_t i = 0;i < theVector.size();i++)
    {
        theSize = 0;
        theVector[i].eleStatus = EMPTY;
        theVector[i].account = 0;
    }
}
template<class Object>
int HashTable<Object>::findPos(const Object& orig)const
{
    int hashValue = myHash(orig);
    int offset = 1;
    while(theVector[hashValue].eleStatus != EMPTY && 
        theVector[hashValue].element != orig)
    {
        hashValue += offset;
        offset +=2;
    }
    return hashValue;
}
template<class Object>
bool HashTable<Object>::contains(const Object& orig)const
{
    return isActive(findPos(orig));
}
template<class Object>
bool HashTable<Object>::isActive(int currentPos)const
{
    if(theVector[currentPos].eleStatus == ACTIVE)
        return true;
    return false;
}
template<class Object>
bool HashTable<Object>::remove(const Object& orig)
{
    int pos = findPos(orig);
    if(isActive(pos))
    {
        theSize--;
        theVector[pos].eleStatus = DELETED;
        theVector[pos].account = 0;        //如果删除就记为0
        return true;
    }
    return false;
}
template<class Object>
bool HashTable<Object>::insert(const Object& orig)
{
    int pos = findPos(orig);
    if(!isActive(pos))
    {
        theSize++;
        theVector[pos].element = orig;
        theVector[pos].eleStatus = ACTIVE;
        theVector[pos].account++;
        return true;
    }
    theVector[pos].account++;        //如果存在就自增一个
    return false;
}
template<class Object>
int HashTable<Object>::myHash(const Object& orig)const
{
    int hashValue = hash(orig)%theVector.size();
    return hashValue;
}
template<class Object>
void HashTable<Object>::printTable()const
{
    for(size_t i = 0;i < theVector.size();i++)
    {
        if(theVector[i].eleStatus == ACTIVE)
            cout << theVector[i].element << " " << theVector[i].account << endl;
    }
}
//Binary Tree
template<class Object>
class BinarySearchTree
{
    public:
    BinarySearchTree();
    BinarySearchTree(const BinarySearchTree& orig);
    const BinarySearchTree& operator = (const BinarySearchTree& orig);
    const Object& findMin()const;
    const Object& findMax()const;
    bool contains(const Object& x)const;
    bool isEmpty()const;
    void printTree()const;

    void makeEmpty();
    void insert(const Object& x);
    void remove(const Object& x);
    private:
    struct BinaryNode
    {
        Object element;
        size_t account;
        BinaryNode* left;
        BinaryNode* right;
        BinaryNode(const Object& orig,BinaryNode* l,BinaryNode* r,size_t num = 1):
                element(orig),left(l),right(r),account(num){}
    };
    BinaryNode* root;
    void insert(const Object& x,BinaryNode* &t)const;
    void remove(const Object& x,BinaryNode* &t)const;
    BinaryNode* findMin(BinaryNode* t)const;
    BinaryNode* findMax(BinaryNode* t)const;
    bool contains(const Object& x,BinaryNode* t)const;
    void makeEmpty(BinaryNode* &t);
    void printTree(BinaryNode* t)const;
    BinaryNode* clone(BinaryNode* t);
};
template<class Object>
BinarySearchTree<Object>::BinarySearchTree()
{
    root = NULL;
}
template<class Object>
BinarySearchTree<Object>::BinarySearchTree(const BinarySearchTree<Object>& orig)
{
    root = clone(orig.root);
}
template<class Object>
const BinarySearchTree<Object>& BinarySearchTree<Object>::operator = (const BinarySearchTree<Object>& orig)
{
    if(this != &orig)
    {
        makeEmpty();
        root = clone(orig.root);
    }
    return *this;
}
template<class Object>
bool BinarySearchTree<Object>::contains(const Object& orig)const
{
    return contains(orig,root);
}
template<class Object>
bool BinarySearchTree<Object>::contains(const Object& orig,typename BinarySearchTree<Object>::BinaryNode* t)const
{
    if(NULL == t)
        return false;
    else if(orig < t->element)
        return contains(orig,t->left);
    else if(t->element < orig)
        return contains(orig,t->right);
    else
        return true;
}
template<class Object>
const Object& BinarySearchTree<Object>::findMin()const
{
    return findMin(root)->element;
}
template<class Object>
typename BinarySearchTree<Object>::BinaryNode* BinarySearchTree<Object>::findMin(BinaryNode* t )const
{
    if(t == NULL)
        return t;
    if(t->left == NULL)
        return t;
    else
        return findMin(t->left);
}
template<class Object>
const Object& BinarySearchTree<Object>::findMax()const
{
    return findMax(root)->element;
}
template<class Object>
typename BinarySearchTree<Object>::BinaryNode* BinarySearchTree<Object>::findMax(BinaryNode* t )const
{
    if(t == NULL)
        return t;
    if(t->right == NULL)
        return t;
    else
        return findMax(t->right);
}
template<class Object>
void BinarySearchTree<Object>::insert(const Object& x)
{
    return insert(x,root);
}
template<class Object>
void BinarySearchTree<Object>::insert(const Object& x,BinaryNode* &t)const
{
    if(t == NULL)
    {
        t = new BinaryNode(x,NULL,NULL,1);
    }
    else if(x < t->element)
        insert(x,t->left);
    else if(t->element < x)
        insert(x,t->right);
    else        //表示存在
    {
        t->account++;
        return;
    }
}
template<class Object>
void BinarySearchTree<Object>::remove(const Object& x)
{
    return remove(x,root);
}
template<class Object>
void BinarySearchTree<Object>::remove(const Object& x,typename BinarySearchTree<Object>::BinaryNode* &t)const
{
    if(t == NULL)    //表示不存在
        return ;
    else if(x < t->element)
        return remove(x,t->left);
    else if(t->element < x)
        return remove(x,t->right);
    else if(t->left != NULL && t->right != NULL)        //two children
    {
        t->element = findMin(t->right)->element;
        remove(t->element,t->right);
    }
    else
    {
        BinaryNode* oldNode = t;
        t->account = 0;        //删除就记为0
        t = (t->left != NULL)?t->left:t->right;
        delete oldNode;
    }
}
template<class Object>
void BinarySearchTree<Object>::makeEmpty()
{
    makeEmpty(root);
}
template<class Object>
void BinarySearchTree<Object>::makeEmpty(typename BinarySearchTree<Object>::BinaryNode* &t)
{
    if(t != NULL)
    {
        makeEmpty(t->left);
        makeEmpty(t->right);
        delete t;
    }
    t = NULL;
}
template<class Object>
typename BinarySearchTree<Object>::BinaryNode* BinarySearchTree<Object>::clone(typename BinarySearchTree<Object>::BinaryNode* t)
{
    if(t == NULL)
        return NULL;
    else
        return new BinaryNode(t->element,clone(t->left),clone(t->right),t->account);
}
template<class Object>
void BinarySearchTree<Object>::printTree()const
{
    printTree(root);
}
template<class Object>
void BinarySearchTree<Object>::printTree(typename BinarySearchTree<Object>::BinaryNode* t)const
{
    if(t != NULL)
    {
        cout << t->element << " " << t->account << endl;
        printTree(t->left);
        printTree(t->right);
    }
}
struct elementNode
{
    char element;
    int account;
};
int main()
{
    string str = "2u390ufjsdjf049oiaefds904t43ijoij235809fdsjgdfg345049385";
    //hashtable 实现
    cout << "using hashtable implementation" << endl;
    HashTable<char> hashtable(1001);
    for(size_t h = 0;h < str.size();h++)
        hashtable.insert(str[h]);
    hashtable.printTable();
    //vector实现O(logN)
    cout << "use vector implementation" << endl;
    vector<elementNode> nodevec(256);
    for(size_t v = 0;v < nodevec.size();v++)    //initialization
    {
        nodevec[v].element = v;
        nodevec[v].account = 0;
    }
    for(size_t v = 0;v < str.size();v++)
    {
        nodevec[str[v]].account++;
    }
    for(size_t v = 0;v < 256;v++)
    {
        if(nodevec[v].account != 0)
            cout << nodevec[v].element << " " << nodevec[v].account << endl;
    }
    //using map implementation
    cout << "using map implementation" << endl;
    map<char,int> cimap;
    for(size_t m = 0;m < str.size();m++)
        cimap[str[m]]++;
    typedef map<char,int>::iterator iter;
    iter beg = cimap.begin();
    for(;beg != cimap.end();beg++)
        cout << beg->first << " " << beg->second << endl;
    cout << "using binary tree implementation" << endl;
    BinarySearchTree<char> binarytree;
    for(size_t b = 0;b < str.size();b++)
    {
        binarytree.insert(str[b]);
    }
    binarytree.printTree();
    return 0;
}
using hashtable implementation
0 5
2 2
3 5
4 5
5 3
8 2
9 5
a 1
d 4
e 1
f 5
g 2
i 3
j 5
o 2
s 3
t 1
u 2
use vector implementation
0 5
2 2
3 5
4 5
5 3
8 2
9 5
a 1
d 4
e 1
f 5
g 2
i 3
j 5
o 2
s 3
t 1
u 2
using map implementation
0 5
2 2
3 5
4 5
5 3
8 2
9 5
a 1
d 4
e 1
f 5
g 2
i 3
j 5
o 2
s 3
t 1
u 2
using binary tree implementation
2 2
0 5
u 2
3 5
9 5
4 5
5 3
8 2
f 5
d 4
a 1
e 1
j 5
i 3
g 2
s 3
o 2
t 1
请按任意键继续. . .


前段时间看到一个帖子的题目,我当时给的答案是vector,对于这个问题比较特殊,用vector其实的确是方便和迅速,然后我写了下map,hashtable,和binarytree的实现
这里比较特殊,因为统计字符的话,字符的范围是确定了。虽然hashtable和vector的时间界都是N,但用hashtable会比vector要慢些,因为要计算hash函数还要判断是否在表中多了很多其他操作。
至于map和binarytree其实都一样,map内部也是用的红黑树,插入和查找都是O(logN),但是这里的时间界限是N*logN就比vector慢。
不过这个问题比较特殊,如果换成单词统计的话那就得用hashtable了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值