3.4 马尔科夫链算法具体实现(C语言)

3.4 马尔科夫链算法具体实现

    在这一篇笔记中,我不打算说很多了。因为所有的理论知识都在3.3节中讨论过了。我在这里直接给出代码。另外给个彩蛋,某公司的面试题可就和这道特别类似哦。

    在这里,我要说的是:

    1.读取文本和代码之间的配合要掌握好

    2.时间与空间消耗要掌握好

    而对于C语言来说,最强的地方就是给了程序员对实现方式的完全控制,用它写出的程序趋向于快速。但是这也有代价,这就是C程序员必须做更多的工作,包括分配和释放存储,建立散列表和链接表,以及其他许多类似的事项。 C语言像一把飞快的剃刀,使用它,你可以创造优雅和高效的程序,或者弄出些一塌糊涂的东西来。

    代码时间:

#include "stdafx.h"
#include "stdlib.h"
#include "string.h"
#include <iostream>

using namespace std;

enum
{
	NPREF = 2,			/*前缀中词的数量*/
	NHASH = 99999,		/*哈希表(散列表)大小*/
	MAXGEN = 10000,		/*录入的最大单词数量*/
	MULTIPLIER = 31,
	BUFSIZE = 100
};
char NONWORD = '\n';

typedef struct State State;
typedef struct Suffix Suffix;
/*散列表中的元素*/
struct State
{
	/*前缀数量是确定的*/
	char *pref[NPREF];
	/*状态中要可以包含后缀及指向下一个前缀*/
	Suffix *suf;
	State *next;
};
/*后缀*/
struct Suffix
{
	char *word;
	/*可以构成多个后缀*/
	Suffix *next;
};
/*这个就是散列表*/
State *statetab[NHASH] = { NULL };

unsigned int hash_number(char *s[NPREF]);
State *lookup(char *prefix[NPREF], int create);
void build(char *prefix[NPREF], FILE *f);
void add(char *prefix[NPREF], char *suffix);
void addsuffix(State *sp, char *suffix);

int main()
{
	State *begin;
	FILE *fp = NULL;
	char box[NPREF][256];
	fp = fopen("..\\test.txt", "r");
	if (fp == NULL)
	{
		cout << "Error in opening the file" << endl;
		exit(0);
	}
	begin = (State *)malloc(sizeof(State));
	begin->next = NULL;
	for (int i = 0; i < NPREF; i++)
	{
		fscanf(fp, "%s", box[i]);
		begin->pref[i] = box[i];
		//cout << begin->pref[i] << endl;
	}
	build(begin->pref, fp);
	for (int i = 0; i < NHASH; i++)
	{
		if (statetab[i] != NULL)
		{
			cout << statetab[i]->pref[0] << " " << statetab[i]->pref[1] << " " << statetab[i]->suf->word << endl;
                        /*插入的位置同样正确*/
			if (statetab[i]->suf->next != NULL)
			{
				cout << statetab[i]->suf->next->word << endl;
			}
		}
	}
    return 0;
}

/*哈希表键值计算函数*/
unsigned int hash_number(char *s[NPREF])
{
	unsigned int h;
	unsigned char *p;
	int i;

	h = 0;
	for (i = 0; i < NPREF; i++)
	{
		for (p = (unsigned char *)s[i]; *p != '\0'; p++)
		{
			h = MULTIPLIER * h + *p;
		}
	}
	/*返回哈希表中的键值*/
	return h;
}

State *lookup(char *prefix[NPREF], int create)
{
	int i, h;
	State *sp = NULL;

	h = hash_number(prefix);
	for (sp = statetab[h]; sp != NULL; sp = sp->next)
	{
		for (i = 0; i < NPREF; i++)
		{
			/*如果输入的prefix和哈希表中对应的sp->pref[i]不相同*/
			/*证明不是要找的前缀*/
			/*注意前缀中含有两个单词*/
			if (strcmp(prefix[i], sp->pref[i]) != 0)
			{
				break;
			}
		}
		if (i == NPREF)
		{
			return sp;
		}
	}
	/*在哈希表中没有与输入前缀相对应的部分时*/
	if (create)
	{
		sp = (State *)malloc(sizeof(State));
		for (i = 0; i < NPREF; i++)
		{
			sp->pref[i] = prefix[i];
		}
		sp->suf = NULL;
		/*将新生成的状态(State)加入到散列表中(哈希表)*/
		sp->next = statetab[h];
		statetab[h] = sp;
	}
	return sp;
}

/*读取文档并且构建前缀、后缀*/

void build(char *prefix[NPREF], FILE *f)
{
	char buf[100], fmt[10];
	//sprintf(fmt, "%%%ds", sizeof(buf) - 1);
	/*将文本中符合“fmt”定义的单词读取到buf中*/
	/*fmt定义为最大99个字符,因为基本所有单词不会超过20个字符*/
	while (fscanf(f, "%s", buf) != EOF)
	{
		/*将符合“fmt”标准的单词复制到buf中*/
		/*使用字符串复制函数strdup*/
		add(prefix, _strdup(buf));
	}
}

/*添加函数,将会把整篇文档都加到散列表中*/
/*遍历文档,文章中所有前缀都能涉及*/
void add(char *prefix[NPREF], char *suffix)
{
	/*定位到prefix,并且把后缀suffix加入到prefix对应的sp中*/
	State *sp;
	sp = lookup(prefix, 1);
	addsuffix(sp, suffix);
	/*前缀的更新*/
	memmove(prefix, prefix + 1, (NPREF - 1) * sizeof(prefix[0]));
	prefix[NPREF - 1] = suffix;
}

/*为某一个特定的前缀添加后缀*/
void addsuffix(State *sp, char *suffix)
{
	Suffix *suf;
	suf = (Suffix *)malloc(sizeof(Suffix));
	suf->word = suffix;
	suf->next = sp->suf;
	sp->suf = suf;
}

猜你喜欢

转载自blog.csdn.net/coulson_zhao/article/details/79959105
3.4