(1)为文档中包含的单词生成一个列表,使用标准模板库中的set容器与string,while循环输入集合S(忽略重复的单词),并排序输出:
#include<iostream>
#include<string>
#include<set>
using namespace std;
int main()
{
set<string> S;
string t;
while (cin >> t)
S.insert(t);
set<string>::iterator i;
for (i = S.begin(); i != S.end(); ++i)
cout << *i<< endl;
return 0;
}
运行结果举例:
(2)利用标准模板库中的关联容器map,统计输入字符串的出现次数
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main()
{
map<string,int> M;
string t;
while (cin >> t)
++M[t];
map<string, int>::iterator i;
for (i = M.begin(); i != M.end(); ++i)
cout << i->first <<" "<< i->second << endl;
return 0;
}
运行结果举例:
为了减少处理时间,可以建立散列表。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node *nodeptr;
typedef struct node
{
char *word;
int count;
nodeptr next;
}node;
#define NHASH 29989 //圣经中有29131个不同的单词,用跟29131最接近的质数作为散列表的大小
#define MULT 31 //hash时用到的乘数
nodeptr bin[NHASH]; //散列表
unsigned int hash(char *p)
{
unsigned int h = 0;
for( ; *p != ''; p++)
{
h = MULT * h + *p;
}
return h % NHASH;
}
#define NODEGROUP 1000
int nodesleft = 0;
nodeptr freenode;
nodeptr nmalloc()
{
if(nodesleft == 0)
{
freenode = (nodeptr)malloc(NODEGROUP *sizeof(node));
nodesleft = NODEGROUP;
}
nodesleft--;
return freenode++;
}
#define CHARGROUP 10000
int charleft = 0;
char *freechar;
char *smalloc(int n)
{
if(charleft < n)
{
freechar = (char *)malloc(n + CHARGROUP);
charleft = n + CHARGROUP;
}
charleft -= n;
freechar += n;
return freechar - n;
}
//增加原先存在的单词的计数值,若之前没有该单词,则对计数器初始化
void incword(char *s)
{
nodeptr p;
int h = hash(s); //找到与单词对应的箱
for(p = bin[h]; p != NULL; p = p->next)
{
if(strcmp(s, p->word) == 0)
{
(p->count)++;
return;
}
}
p = nmalloc();
p->count = 1;
p->word = smalloc(strlen(s) + 1);
strcpy(p->word, s);
p->next = bin[h]; //头插法
bin[h] = p;
}
int main()
{
int i;
nodeptr p;
char buf[100];
for(i = 0; i < NHASH; i++)
{
bin[i] = NULL;
}
while(scanf("%s", buf) != EOF)
{
incword(buf);
}
for(i = 0; i < NHASH; i++)
{
for(p = bin[i]; p != NULL; p = p->next)
{
printf("%s %dn", p->word, p->count);
}
}
return 0;
}
性能分析:
平衡搜索树将字符串看作不可分割的一部分进行操作,STL中的set和map中的大部分实现都是使用这种数据结构。散列表则需要深入字符串的内部,计算散列函数并将关键字分散到一个较大的表中。散列表的方法平均速度很快,但是缺乏平衡树提供的最坏情况性能保证,也不能支持其他设计顺序的操作。