------------------
------------------ fuck "顶“
------------------
在<<the practice of programming>>第三章中,两位作者举了一个markov算法的例子,文章一开头,作者以Frederick P. Brook的名言来说明了数据结构的重要性-"如果你只给我看流程图,不给我看你的数据结构表,我可能还是很困惑;如果你给我看了你的数据结构表,流程图有些时候并不重要,流程太明显了"。
两位作者举了一个非常有趣的例子,利用文本中已经有的文本组合成新的文本。
需要注意的是,作者没有初始化hash数组。以下是一些亮点:
1. 判断两个数组相等的技法
2. 正确在链表中随机选择一个节点的方法
3. hash技法
4. 如何开始,如何结束
5. 开始时,并没有两个previous,巧妙地使用了文本中不存在的字符当作previous,任何输入的字符都是suffix.
6. 最后一个节点没有suffix,使用文本中不存在的字符当做suffix.
平时自己写了太多的C++程序,经过这个程序,C语言功力有点提升。
// markov.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
enum
{
NHASH = 5000,
MULTIPLIER = 37,
NPREV = 2
};
typedef struct Suffix Suffix;
typedef struct State State;
struct State
{
char *prev[NPREV];
Suffix *suf;
State *next;
};
char NOWORD[] = "/n";
struct Suffix
{
char *word;
Suffix *next;
};
State *sHash[NHASH];
int hash(char *prev[NPREV])
{
assert(prev);
int h = 0;
for (int i = 0; i < NPREV; ++i)
for (char *p = prev[i]; *p != '/0'; ++p)
h = MULTIPLIER * h + *p;
h = h % NHASH;
if (h < 0) //防止负数溢出
h = h + NHASH;
return h;
}
State *LookUp(char *prev[NPREV], int create)
{
int h = hash(prev);
State *sp = NULL;
for (sp = sHash[h]; sp != NULL; sp = sp->next)
{
int i = 0;
for (; i < NPREV; ++i)
{
if (strcmp(sp->prev[i], prev[i]) != 0)
break;
}
if (i == NPREV)
return sp;
}
if (create == 1)
{
sp = (State*)malloc(sizeof(State));
sp->suf = NULL;
for (int i = 0; i < NPREV; ++i)
sp->prev[i] = prev[i];
sp->next = sHash[h];
sHash[h] = sp;
return sp;
}
return NULL;
}
void AddSuffix(State *pState, char *suffix)
{
assert(pState && suffix);
Suffix *pSuffix = (Suffix*)malloc(sizeof(Suffix));
pSuffix->word = suffix;
pSuffix->next = pState->suf;
pState->suf = pSuffix;
}
void Add(char *prev[NPREV], char *suffix)
{
State *s = LookUp(prev, 1);
if (!s)
return;
AddSuffix(s, suffix);
memmove(prev, prev + 1, (NPREV - 1) * sizeof(prev[0]));
prev[NPREV - 1] = suffix;
}
void Build(char *prev[NPREV], FILE *f)
{
char buf[100], fmt[10];
sprintf(fmt, "%%%ds", sizeof(buf) - 1);
while (fscanf(f, fmt, buf) != EOF)
{
Add(prev, strdup(buf));
}
}
void Clear()
{
}
void Generate(int nwords)
{
char *prev[NPREV];
char *w;
for (int i = 0; i < NPREV; ++i)
prev[i] = NOWORD;
State *sp = NULL;
for (int i = 0; i < nwords; ++i)
{
sp = LookUp(prev, 0);
int nmatch = 0;
for (Suffix *pSuf = sp->suf; pSuf != NULL; pSuf = pSuf->next)
{
if (rand() % ++nmatch == 0)
w = pSuf->word;
}
if (strcmp(w, NOWORD) == 0)
break;
printf("%s/n", w);
memmove(prev, prev + 1, (NPREV - 1) * sizeof(prev[0]));
prev[NPREV - 1] = w;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
srand(time(NULL));
FILE *f = fopen("c://a.txt", "r");
if (f == NULL)
goto END;
char *prev[NPREV] = {
NOWORD,
NOWORD
};
for (int i = 0; i < NHASH; ++i)
sHash[i] = NULL;
Build(prev, f);
Add(prev, NOWORD);
Generate(1000);
Clear();
fclose(f);
END:
system("pause");
return 0;
}
------------------ fuck "顶“
------------------
在<<the practice of programming>>第三章中,两位作者举了一个markov算法的例子,文章一开头,作者以Frederick P. Brook的名言来说明了数据结构的重要性-"如果你只给我看流程图,不给我看你的数据结构表,我可能还是很困惑;如果你给我看了你的数据结构表,流程图有些时候并不重要,流程太明显了"。
两位作者举了一个非常有趣的例子,利用文本中已经有的文本组合成新的文本。
需要注意的是,作者没有初始化hash数组。以下是一些亮点:
1. 判断两个数组相等的技法
2. 正确在链表中随机选择一个节点的方法
3. hash技法
4. 如何开始,如何结束
5. 开始时,并没有两个previous,巧妙地使用了文本中不存在的字符当作previous,任何输入的字符都是suffix.
6. 最后一个节点没有suffix,使用文本中不存在的字符当做suffix.
平时自己写了太多的C++程序,经过这个程序,C语言功力有点提升。
// markov.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
enum
{
NHASH = 5000,
MULTIPLIER = 37,
NPREV = 2
};
typedef struct Suffix Suffix;
typedef struct State State;
struct State
{
char *prev[NPREV];
Suffix *suf;
State *next;
};
char NOWORD[] = "/n";
struct Suffix
{
char *word;
Suffix *next;
};
State *sHash[NHASH];
int hash(char *prev[NPREV])
{
assert(prev);
int h = 0;
for (int i = 0; i < NPREV; ++i)
for (char *p = prev[i]; *p != '/0'; ++p)
h = MULTIPLIER * h + *p;
h = h % NHASH;
if (h < 0) //防止负数溢出
h = h + NHASH;
return h;
}
State *LookUp(char *prev[NPREV], int create)
{
int h = hash(prev);
State *sp = NULL;
for (sp = sHash[h]; sp != NULL; sp = sp->next)
{
int i = 0;
for (; i < NPREV; ++i)
{
if (strcmp(sp->prev[i], prev[i]) != 0)
break;
}
if (i == NPREV)
return sp;
}
if (create == 1)
{
sp = (State*)malloc(sizeof(State));
sp->suf = NULL;
for (int i = 0; i < NPREV; ++i)
sp->prev[i] = prev[i];
sp->next = sHash[h];
sHash[h] = sp;
return sp;
}
return NULL;
}
void AddSuffix(State *pState, char *suffix)
{
assert(pState && suffix);
Suffix *pSuffix = (Suffix*)malloc(sizeof(Suffix));
pSuffix->word = suffix;
pSuffix->next = pState->suf;
pState->suf = pSuffix;
}
void Add(char *prev[NPREV], char *suffix)
{
State *s = LookUp(prev, 1);
if (!s)
return;
AddSuffix(s, suffix);
memmove(prev, prev + 1, (NPREV - 1) * sizeof(prev[0]));
prev[NPREV - 1] = suffix;
}
void Build(char *prev[NPREV], FILE *f)
{
char buf[100], fmt[10];
sprintf(fmt, "%%%ds", sizeof(buf) - 1);
while (fscanf(f, fmt, buf) != EOF)
{
Add(prev, strdup(buf));
}
}
void Clear()
{
}
void Generate(int nwords)
{
char *prev[NPREV];
char *w;
for (int i = 0; i < NPREV; ++i)
prev[i] = NOWORD;
State *sp = NULL;
for (int i = 0; i < nwords; ++i)
{
sp = LookUp(prev, 0);
int nmatch = 0;
for (Suffix *pSuf = sp->suf; pSuf != NULL; pSuf = pSuf->next)
{
if (rand() % ++nmatch == 0)
w = pSuf->word;
}
if (strcmp(w, NOWORD) == 0)
break;
printf("%s/n", w);
memmove(prev, prev + 1, (NPREV - 1) * sizeof(prev[0]));
prev[NPREV - 1] = w;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
srand(time(NULL));
FILE *f = fopen("c://a.txt", "r");
if (f == NULL)
goto END;
char *prev[NPREV] = {
NOWORD,
NOWORD
};
for (int i = 0; i < NHASH; ++i)
sHash[i] = NULL;
Build(prev, f);
Add(prev, NOWORD);
Generate(1000);
Clear();
fclose(f);
END:
system("pause");
return 0;
}