1. 程式人生 > 實用技巧 >廣度遍歷-二叉樹最小深度

廣度遍歷-二叉樹最小深度

此作業的要求參見:https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11206

功能1 小檔案輸入。 為表明程式能跑,結果真實而不是迫害老五,請他親自鍵
盤在控制檯下輸入命令。
為了評估老五的詞彙量而不是閱讀量,total一項中相同的單詞不重複計數數,出現2次的very計數1次。
因為用過控制檯和命令列,你早就知道,上面的">"叫做命令提示符,是作業系統的一部分,而不是你的程式的一部分。
此功能完成後你的經驗值+10.
功能一的執行截圖如下:
小檔案的輸入,讀取test.txt檔案 sort函式排序後輸出

次功能中type 輸出test.txt的文字內容

功能2 支援命令列輸入英文作品的檔名,請老五親自錄入。
讀取文章的名字,然後在文章的名字後面加上詞綴.txt,然後就和第一個功能一樣了,由於單詞的數量會很大所以陣列要定義的的大一點,
在最開始初步定義不會重複的單詞數量不超過1000000的max上屆值。
功能二執行截圖

功能3 支援命令列輸入儲存有英文作品檔案的目錄名,批量統計。

因為單詞量巨大,只列出出現次數最多的10個單詞。
功能三執行截圖
讀取資料夾的名字,和第二個功能不一樣的地方在獲得的字串後面加上.txt的檔案字尾,生成fileName,
然後用_findfirst()函式實現資料夾處理,如果返回結果為-1,則說明輸入的是文章的名字而不是資料夾的地址
剩下的輸出和第一個功能相同,也是sort排序後輸出。

功能4 從控制檯讀入英文單篇作品,這不是為了打臉老五,而是為了向你女朋
友炫酷,表明你能提供更適合嵌入指令碼中的作品(或者如她所說,不過是更靈活
的介面)。如果讀不懂需求,請教師兄師姐,或者 bing: linux 重定向,儘管
這個功能在windows下也有,搜尋關鍵詞中加入linux有利於迅速找到。

功能四執行截圖
這個功能的實現上有一些問題還沒有解決,在過載<並執行輸出後的文章的wordtotal數沒有將重複的單詞數去掉

發表部落格,介紹上述“專案”中每個功能的重點/難點,展示重要程式碼片斷,給出執行效果截圖,展示你感覺得意、突破、困難的地方。

首先,要感謝我的師兄在程式碼實現上的幫助和耐心的講解,因為自身的能力很差,所以實現的非常困難。
以及在coding和git設定的時候室友的幫助
此處附上我們在完成git相關配置時參考的部落格地址:

https://blog.csdn.net/gyy930324/article/details/54575246
在讀完題目要求以後我查找了很多c和c++相關的內容,首要的就是對檔案的取讀操作,參考了下面的部落格內容
https://blog.csdn.net/naibozhuan3744/article/details/80610476?utm_medium=distribute.pc_relevant.none-task-blog-title-1&spm=1001.2101.3001.4242
https://blog.csdn.net/baidu_29950065/article/details/51659913?yyue=a21bo.50862.201879
https://blog.csdn.net/sub_lele/article/details/78007919?utm_medium=distribute.pc_relevant.none-task-blog-title-1&spm=1001.2101.3001.4242
https://blog.csdn.net/hqw7286/article/details/5603403
對於整個功能實現,首先總結出需要解決的關鍵點:
檔案的取讀;單詞的大小寫轉換;對空格和特殊符號的處理;對單詞的hash構造;對詞頻的排序;重定向
1.下面是實現檔案取讀的重點程式碼,
首先是定義了單詞頻率和單詞自身的結構體

//結構體WORDS 定義單詞和頻率,在此過載了"<"
struct WORDS{
    int freq;//頻率 
    char content[50];//單詞自身 
    bool operator < (const WORDS &rhs) const {
        return freq > rhs.freq;
    }
}words[Max];

2.檔案輸入,用到fopen()函式,定義FILE變數fp,用fgetc()函式讀取檔案中的內容,
然後用feof()函式判定檔案是否遍歷結束,最後用fclose()函式關閉
bool定義了一個before的變數用來判斷前一個是否是字母

//將輸入處理成單個單詞
void inputword(char name[]) 
{
    fp=fopen(name, "r");  
    //用fopen開啟檔案從而進行輸入
    before=1;
    wordfreq=0;
    wordtotal=0;
    int i=0;
    memset(words,0,sizeof(*words));
    //memset函式的作用在於將後面內容變成ascii碼方便後續的大小寫轉換 
    while(!feof(fp)) {   
	//用於構造單詞,把大寫字母變為小寫
        ch=fgetc(fp);
        if((ch>=65&&ch<=90)||(ch>=97&&ch<=122)) {
            if(ch>=65&&ch<=90) 
            ch+=32;
            word[i++]=ch;
            before=1;
        }
        else {
            if(before) {
                word[i]='\0';
                Hash(word);
	//將構造出來的單詞hash插入結構體words中
                i=0;
                before=0;
            }
        }
    }
    fclose(fp);
    fp=NULL;
    return;
}

3.在對單詞的儲存的考慮時請教師兄說可以使用雜湊的思想來進行實現,用hash的方式將單詞存入最開始構建的單詞的結構體中,
具體的思想是小於三個的字母就按其字母的數量進行插入,大於三個的單詞取前三個字母的值組合成六位數然後對最開始設定的最大上屆值取餘操作得到的值進行雜湊的插入,如果該位置有字母了就後移插入。

//用hash的方法去把每個單詞插入到結構體中
void Hash(char word[]) 
{
    int len=strlen(word);
    if(len>=6) 
	len = 6;
    int i,t = 0;
    for(i=0;i<len;i++) {
        t=t*10;
        t+=(word[i]-97);
    }
    t=t%Max;
    for(i=t;i<Max;i++) {
        if(words[i].freq==0) {
            words[i].freq=1;
            strcpy(words[i].content,word);
            //對單詞進行復制 
            wordtotal+=1;
            wordfreq+=1;;
            return;
        }
        else {
            if(strcmp(words[i].content,word)==0) {
            	//比較單詞是否相同 
                words[i].freq+=1;
                wordtotal+=1;
                return;
            }
            else
            {
            	if(t==Max-1)
            	t=0;
            	else
            	t+=1;
	    }
        }
    }
}

4.再然後是對於功能三中的資料夾處理查找了_finddata_t結構體和_findfirst與_findnext函式的使用
參考了此部落格的內容:https://blog.csdn.net/wangqingchuan92/article/details/77979669

//功能三
bool three(char fileName[]) 
{
    strcat(fileName, "\\*.txt");
    //用strcat函式連線檔名和txt的字尾進行區別 
    long k=HANDLE=_findfirst(fileName, &file);
    if(k==-1) 
	return false; 
	//得到的資料夾名字後面加.txt
	//如果能找到就說明輸入的是資料夾的名字
    else {
        while (k!=-1) {
            printf("%s\n", file.name);
            solve(file.name);
            output();
            k=_findnext(HANDLE, &file);
            if(k!=-1) 
	    printf("----\n");
        }
        _findclose(HANDLE);
    }
    return true;
}

5.對於檔案輸出格式,保證只輸出前10個出現頻率最高的單詞,當單詞數不夠10個的時候就直接順序輸出,用sort()函式排序後輸出。以'\t'進行空格的控制

//對於結果的輸出函式
void output()
{
    int i,j,len;
    len=strlen(words[i].content);
    for(i=0;i<((wordfreq<10)?wordfreq:10);i++)
    {
        printf("%s",words[i].content);
        for(j=0;j<3-(len/8);j++)
        {
            printf("\t");
            printf("%d\n",words[i].freq);
        }
    }
}

PSP
(8分)

在同一篇部落格中,參照教材第35頁表2-2和表2-3,為上述“專案”製作PSP階段表格。
PSP階段表格第1列分類,如功能1、功能2、測試功能1等。
要求1 估算你對每個功能 (或/和子功能)的預計花費時間,填入PSP階段表格,時間顆粒度為分鐘。
要求2 記錄詞頻統計專案實際花費時間,填入PSP階段表格,時間顆粒度要求分鐘。
要求3 對比要求1和要求2中每項時間花費的差距,分析原因。

程式碼及版本控制
(5分。雖然只有5分,但此題如果做錯,因為教師得不到你的程式碼,所以會導致“功能實現”為負分。)

本次作業的程式碼地址:https://mochi0828.coding.net/public/wordfreq/homework/git