解字谜

安稳与你 提交于 2019-12-25 03:56:08

不知道咕咕了多久,我已经记不起来多久没更新了,主要是嘿嘿嘿,妹子太好康了,看着看着就不想写了。嗯,今天就先跟新一点,以后保持活跃呀。

问题介绍

其实是一个挺常见的问题哈,就是大家经常在说说里看到的——一张图,然后说什么第一眼看到的三个单词将会带给你好运啥的(主要是有时候我找了半天也找不出三个像样的单词很气),我们要实现一个利用DFS查找单词的程序。

在这里插入图片描述

简单的思路

  1. 利用for循环来遍历每个节点,对该节点进行DFS
  2. 将当前的单词存储在单词栈内,判断该栈中的单词是否为单词或者是某单词的前缀
    a.如果是单词,则输出一下,转b
    b.如果是前缀,继续DFS
    c.如果啥都不是,那么肯定就不是了,退出DFS

附代码

/**
 * 解字谜游戏
 *      输入:首先是一个 n*m 限制一下矩形的区域
 *      输出:单词表中存在的所有单词
 */

#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "words.txt" //这是单词表
#define MAX_WIDE 40 //最大的宽度

/* 全局变量 */
int row;//行数
int col;//列数
int dx[] = {1,-1,0,0}; //控制DFS移动
int dy[] = {0,0,1,-1};
int  vis[MAX_WIDE][MAX_WIDE];//DFS标记
char wordsMap[MAX_WIDE][MAX_WIDE];
char curWords[20];
int  lenth;

/* 键树的结构 */
typedef struct Node
{
    char key;//关键字
    struct Node* child; //孩子
    struct Node* brother; //兄弟
    int wordsTag; //标记是不是单词
}NODE;
typedef NODE* Tree;

/* 函数声明 */
void getInfo();//输入图
Tree buildNode(char c);//创建节点
Tree buildKeyTree();//建立键树
int  isWords(Tree T);//查找
void DFS(int x,int y,Tree T);//搜索
void printWords();//打印
void addWords(Tree T,char s[]);//添加树节点
void showTree(Tree T);//展示树

int main()
{
    Tree T = buildKeyTree();
//    showTree(T);
    getInfo();
    for(int i=0;i<row;i++)
        for(int j=0;j<col;j++)
            DFS(i,j,T);
        
    return 0;
}

/* 函数声明 */
void getInfo()//输入图
{
    scanf("%d %d",&row,&col);getchar();//后摇
    for(int i=0;i<row;i++)
        gets(wordsMap[i]);
    printf("输入完成,请耐心等待查询结果\n"); 
}
Tree buildNode(char c)//创建节点
{
    Tree tmp = (Tree)malloc(sizeof(NODE));
    tmp->child = tmp->brother = NULL;
    tmp->wordsTag = 0;
    tmp->key = c;
    return tmp;
}
void addWords(Tree T,char s[])//添加树节点
{
    /* 先指向对应的键 */
    while (T->brother != NULL && T->brother->key <= s[0])
        T = T->brother;
    /* 是否有这个值 */
    if(T->key != s[0]) //无
    {
        Tree tmp = buildNode(s[0]);
        tmp->brother = T->brother;
        T->brother = tmp;
        T=T->brother;
    }
    /* 单词读入,退出 */
    if(s[1] == '\n' ||s[1] == '\0') //这主要是应为fgets的关系
    {
        T->wordsTag = 1;
        return;
    }
    /* 该节点是否有孩子节点 */
    if(T->child == NULL)
    {
        T->child = buildNode('a'); //这里先建立一个'a'节点方便进入
    }
    addWords(T->child,&s[1]);
}
Tree buildKeyTree()//建立键树
{
    Tree T =buildNode('a');//树根
    /* 建树 */
    char s[20];
    FILE *fp;
    if((fp=fopen(FILE_NAME,"r"))==NULL)
    {
        printf("fail to open\n");
        exit(0);
    }
    while ((fgets(s,20,fp)!= NULL))
    {
        addWords(T,s);
    }
    
    return T;
}
int  isWords(Tree T)//查找
{
    int i=0;
    while (1)
    {
        /* 退出 */
        if(T == NULL)
            return 0;
        /* 先指向当前的节点 */
        while ( T->brother != NULL && T->key < curWords[i])
            T = T->brother;
        if(curWords[i] != T->key)
            return 0;
        
        if(++i==lenth)
            break;
        T = T->child;
    }
    // return T->wordsTag == 1? 1:2; //1表示这个是单词 2表示可能是单词 可能多次输出一个单词
    if(T->wordsTag==1)
    {
        T->wordsTag = 0;
        return 1;
    }
    else 
        return 2;
}
void DFS(int x,int y,Tree T)//搜索
{
    /* 越界退出 || 被访问退出 */
    if(x<0 || x>=row || y<0 || y>= col || vis[x][y])
        return;
    /* 对当前节点处理 */
    vis[x][y] = 1; //标记
    curWords[lenth++] = wordsMap[x][y]; //添加
    int checkAns = isWords(T);
    if(checkAns)
    {
        if(checkAns == 1)//如果是单词
            printWords();
        for(int i=0;i<4;i++)
            DFS(x+dx[i],y+dy[i],T);
    }
    
    lenth--;
    vis[x][y] = 0;
}
void printWords()//打印
{
    for(int i=0;i<lenth;i++)
        putchar(curWords[i]);
    putchar('\n');
}
void showTree(Tree T)//展示树
{
    /* 空退出 */
    if(T==NULL)
        return;
    /* 加到单词栈 */
    curWords[lenth++] = T->key;
    if(T->wordsTag == 1)
        printWords();
    showTree(T->child);

    lenth--;
    showTree(T->brother);
}


传送门: 来我的博客玩耍呀!有单词表分享!!!

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!