大數據檢索(窗口界面界面演示型)

單詞(詞組)檢索算法

如今有一個英文字典(每一個單詞都是由小寫的'a'-'z'組成) ,單詞量很大,達到 100 多萬的單詞,並且還有不少重複的單詞。數組

此外,咱們如今還有一些 Document,每一個 Document 包含一些英語單詞。數據結構

針對這個問題,請你選擇合適的數據結構,組織這些數據,使時間複雜度和空間複雜度測試

儘量低,而且解決下面的問題和分析本身算法的時間複雜度。ui

1)基本型問題 spa

(1)選擇合適的數據結構,將全部的英文單詞生成一個字典 Dictionary。指針

(2)給定一個單詞,判斷這個單詞是否在字典 Dictionary中。若是在單詞庫中,輸出這個單詞總共出現的次數。不然輸出 NO擴展:code

2)擴展型問題 blog

(3)給定一個單詞,按字典序輸出字典 Dictionary 中全部以這個單詞爲前綴的單詞。例如,若是字典 T={a,aa, aaa, b, ba}, 若是你輸入 a,那麼輸出應該爲{a, aa, aaa}。排序

(4)給定一個單詞,輸出在Dictionary 中以這個單詞爲前綴的單詞的出現頻率最高的10個單詞,對於具備相同出現次數的狀況,按照最近(即最後)插入的單詞優先級比較高的原則輸出。

(5)輸出 Dictionary 中出現次數最高的 10個單詞。

 

程序所能達到的功能:

(1)創建字典

1)查單詞的出現頻

3)輸出以單詞爲的全部單詞

4及其中率最高的十個單詞

5所有單詞率最高的十個單詞

//注:在工程項目文件中放入待排序單詞的tex文檔

#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<time.h>
FILE *out;//設置全局變量,用於遞歸程序
static int pd=0;//遞歸搜索所有單詞中頻率最高的10個單詞爲單詞後,pd 仁然保持爲1
struct TrieNode
{               char c;
    char word[50];
    struct TrieNode  *next[26];
    long count;
};
typedef struct 
{
    char pl[50];
    long mount;
}PINLV;
typedef PINLV pinlv[10];
pinlv b;//設置全局變量,用於遞歸程序

void chushihua(TrieNode *&p)
{                int i;
    (*p).c='#';
    for(i=0;i<50;i++)
    p->word[i]='\0';
    for(i=0;i<26;i++)
    p->next[i]=NULL;
    p->count=0;
}

struct TrieNode* JLTrieNode(TrieNode *root,char s[50])
{                int i,j;
    struct TrieNode *q,*p;
    q=root;    
    for(i=0;s[i]!='\0';i++)
    {
        if(q->next[s[i]-'a']!=NULL)
            q=q->next[s[i]-'a'];
        else 
        {   p=(struct TrieNode *)malloc(sizeof(struct TrieNode));
            q->next[s[i]-'a']=p;
            p->c=s[i];     p->count=0;//初始化節點值
            for(j=0;j<50;j++)
                p->word[j]='\0';
            for(j=0;j<26;j++)
                p->next[j]=NULL;
                q=q->next[s[i]-'a'];
        }    
    }
    q->count++;
    strcpy(q->word,s);                
    return root;
}

long bianli(struct TrieNode *root)//遍歷字典樹並將單詞按字母表順序輸出
{    
    int i;    
    static long j=0,zonggong=0;
    struct TrieNode *p;
                 for(i=0;i<26;i++)
    {    p=root->next[i];
            if(p!=NULL)
        {   if((*p).count!=0) //***********
            {      
                if(j%2==0)  fprintf(out,"\n"); //將全部排好序的單詞存於磁盤中
                else        fprintf(out,"     ");
                fprintf(out,"(%d)%-35s %-5d",j,(*p).word,(*p).count); 
                
                //在窗口中輸出全部的已排好序的單詞
                /*if(j%2==0)  printf("\n"); 
                else printf("           ");
                printf("(%d)%-20s ",j,(*p).word);  
                printf("%-4d",(*p).count);
                */
                zonggong+=(*p).count;
                j++;
            }
            zonggong=bianli(p);
        }
    }
    return zonggong;
}

void digui(struct TrieNode *q, pinlv &a)
{   
                   int i,j,k; 
    if((*q).c=='#')   
        pd=1;
                  struct TrieNode *p;
    j=0;/**********444444444444444444444444*/
    for(i=0;i<26;i++)
    {    p=q->next[i];
        if(p!=NULL)
        {   if((*p).count!=0) //***********
            {   if(pd!=1)//(3)輸出以單詞***爲前綴的全部單詞***3333333333333333333333
                  printf("%s ",(*p).word);//(若q爲根節點,則能夠用於遍歷整個字典樹)                           
                //*****將頻率最高的10個單詞記錄在a[j].pl中********444444444444*/
                for(j=0;j<10;j++)
                {   if((*p).count>a[j].mount)
                    {   for(k=9;k>=j+1;k--)
                        {   strcpy(a[k].pl,a[k-1].pl);                         
                            a[k].mount=a[k-1].mount;
                        }
                        strcpy(a[j].pl,(*p).word); 
                        a[j].mount=(*p).count;
                        break;
                    }              
                }
                //********4444444444444444444444444444************************/        
            }
        digui(p,a);
        }
    }    
}

void chazhao(struct TrieNode *root,char str[50])
{    int i,j,pan=0; 
    pinlv a;//(第4問)**************************
    for(i=0;i<10;i++)//對字符數組pinlv a進行初始化(pinlv a中存放以***爲前綴的頻率最高的10個單詞)
    {    for(j=0;j<50;j++)
        a[i].pl[j]='\0';
        a[i].mount=0;
    }       
    struct TrieNode *q;
    q=root;
    for(i=0;str[i]!='\0';i++)//根據str在樹中搜索:是否存在這個單詞
    {   if(q->next[str[i]-'a']!=NULL)
           q=q->next[str[i]-'a'];  
       else
       {  printf("沒有這個單詞\n"); break;}//若是單詞還未遍歷結束(str[i]!='\0'),
                                         //就指向了NULL,說明該單詞不在「文檔」中(即不在字典樹中)
    }
    if(str[i]=='\0')
    {   printf("文檔中單詞%s共有%d個\n",str,q->count);//(第2問)**輸出以單詞str[]的個數

                   printf("文檔中以單詞%s爲前綴的單詞有:\n",str);//(第3問)**輸出以單詞str[]爲前綴的單詞
        digui(q,a);//(3,4問)在遞歸程序中輸出以單詞str[]爲前綴的全部單詞,
                                 //而且記錄以單詞str爲前綴的頻率最高的10個單詞爲單詞於pinlv a中
        
        //(第4問)輸出以單詞str爲前綴的頻率最高的10個單詞爲單詞********************/
        if(a[0].mount==0) 
            printf("!!!沒有以單詞%s爲前綴的單詞 ",str);
        else
        {   printf("\n以單詞%s爲前綴的頻率最高的10個單詞爲單詞:\n",str);
            for(i=0;i<10;i++)
            {   printf("(%d)%-10s ",i,a[i].pl);
                printf("%d\n",a[i].mount);
            }
        } 
        //(第4問)輸出以單詞str爲前綴的頻率最高的10個單詞爲單詞*******************/
    }
}

int main()
{   
    /***********************測試建樹的時間***********************************/
                   double duration;
                  clock_t start= clock();//******運行時間測試開始
    char s[50]={'\0'};

    int i,k;
    struct TrieNode *root;
    FILE *fp;
    fp=fopen("文檔.txt","r");
                  root=(struct TrieNode *)malloc(sizeof(struct TrieNode));
    chushihua(root);//初始化頭結點指針
    while(!feof(fp))//從文檔中換行讀取數據
    {    
        fscanf(fp,"%s",s);
        root=JLTrieNode(root,s);//(第1問)創建字典樹
    };
    
    clock_t finish = clock();//*****運行時間測試結束
    duration = (double)(finish-start);//CLOCKS_PER_SEC;
                  printf( "建樹時間爲: %5.3f ms\n",duration ); 
    fclose(fp);
    /**************************************************************************/

    out=fopen("單詞排序.txt","w");//打開一個文檔,存放全部單詞的按字母排序
    long zonggong;  
    zonggong=bianli(root);//遍歷字典樹
    printf("\n總共有%d個單詞\n",zonggong);//輸出總共的單詞個數
    
    for(i=0;i<10;i++)//對字符數組pinlv b進行初始化(pinlv b 存放頻率最高的十個單詞及其頻率)
    {    
        for(k=0;k<50;k++)
            b[i].pl[k]='\0';
        b[i].mount=0;
    } 
    //(第5問)在遞歸算法中將頻率最高的10個單詞記錄在b[j].pl中
            digui(root,b);
            printf("所有單詞中頻率最高的10個單詞爲單詞:\n");//輸出所有單詞中頻率最高的10個單詞爲單詞
            for(i=0;i<10;i++)
    {   
        printf("(%d)%-10s ",i,b[i].pl);
        printf("%d\n",b[i].mount);
    }
            printf("\n");
    
    pd=pd-1;//digui(root,b)後pd一直保持爲1
    char panduan; 
    char str[50]={'\0'};//存放要查找的單詞
    panduan='y';
    while(panduan=='y')
    {    
        printf("請輸入要查找的單詞:");
        scanf("%s",str);
                        //(2,3,4問)輸出文檔中以***爲前綴的全部單詞,並輸出其中頻率最高的10個單詞    
        chazhao(root,str);    
        printf("\n是否繼續?y/n:");    
        do
        {  getchar();
            panduan=getchar();//僅輸入一個字符,不容許多輸入
                           if(!(panduan=='y'||panduan=='n'))          
              printf("輸入字符錯誤,請從新輸入(y/n)!");
        }while( !((panduan=='y')||(panduan=='n')) );
    }        
        return 0;
}
相關文章
相關標籤/搜索