问题描述:一个保存有阿拉伯数字与字母的字符串,存在重复的字符,用以下哪一种容器可以最快的统计出每个字符出现的次数?
A vector B set C map D hashtable
前段时间看到一个帖子的题目,我当时给的答案是vector,对于这个问题比较特殊,用vector其实的确是方便和迅速,然后我写了下map,hashtable,和binarytree的实现
这里比较特殊,因为统计字符的话,字符的范围是确定了。虽然hashtable和vector的时间界都是N,但用hashtable会比vector要慢些,因为要计算hash函数还要判断是否在表中多了很多其他操作。
至于map和binarytree其实都一样,map内部也是用的红黑树,插入和查找都是O(logN),但是这里的时间界限是N*logN就比vector慢。
不过这个问题比较特殊,如果换成单词统计的话那就得用hashtable了
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了