2017q1 Homework1 (phonebook) === contributed by < `leocorter` > 新手上路請多多指教 ### Reviewed by `king1224` * 我在你的 github 上沒有看到你的 BST 版本的程式碼 * 你在 stackoverflow 上看到的程式碼是以 double 做為鍵值來比較判斷要放左子樹 or 右子樹,本次 phonebook 是以 lastname 做為鍵值,請問你是如何判斷該往左子樹 or 右子樹走 * 關於 main.c 中的 append() 使用,原始版本可以傳入整串資料的任意節點,畢竟原始版本的儲存方式沒有分支,但對於 BST 結構來說,每次都需要傳入 root,因此 main.c 中的使用方式需修改 ### Reviewed by `tina0405` *關於BINARYTREE我本身是嘗試用字數長短判斷左右,想了解是以和者為判斷標準。 *還有你將STRUCTURE只分為左子樹和右子樹那其他的資料要如何去呼叫,之後在使用這份電話簿時,還是會運用到其他資訊。 *其他方面也可測試不同的hashfunctin嘗試。 ## 開發環境 ``` shell Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 8 Vendor ID: GenuineIntel Model name: Intel(R) Core(TM) i7-3632QM CPU @ 2.20GHz CPU MHz: 1243.343 CPU max MHz: 3200.0000 CPU min MHz: 1200.0000 BogoMIPS: 4389.95 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 6144K ``` --- ## 未優化版本 ```clike= /* original version */ entry *findName(char lastName[], entry *pHead) { while (pHead != NULL) { if (strcasecmp(lastName, pHead->lastName) == 0) return pHead; pHead = pHead->pNext; } return NULL; } ``` 很單純的找不到就換下一個 * 執行: `$ ./phonebook_orig` * append() 及 findName() 時間如下 ``` size of entry : 136 bytes execution time of append() : 0.189302 sec execution time of findName() : 0.005467 sec ``` ``` Performance counter stats for './phonebook_orig' (100 runs): 212,2953 cache-misses # 95.108 % of all cache refs ( +- 0.12% ) 223,2152 cache-references ( +- 0.14% ) 2,6081,7801 instructions # 1.43 insns per cycle ( +- 0.02% ) 1,8211,8763 cycles ( +- 0.49% ) 0.088154008 seconds time elapsed ( +- 1.88% ) ``` >進度請加快[name=亮谷][color=#f64] --- ## phonebook ### 改進方向 * binary search tree * hashing function 加入查詢 * 降低資料表示的成本 S --- ## Binary search tree ### 想法: * 如果我們只要找 lastName 這個字串那麼 entry 裡面的其他資料就是多餘的,所以我就把其他資料刪除。 * 原本的資料是用 linked list 一個一個串起來,現在我想要建造一個 binary tree 所以加上了左右的連結。 ``` clike typedef struct __PHONE_BOOK_ENTRY { char lastName[MAX_LAST_NAME_SIZE]; struct __PHONE_BOOK_ENTRY *pNext_left; struct __PHONE_BOOK_ENTRY *pNext_right; } entry; ``` 可是再我實作的過程中遇到了 segmentation fault 後來檢查是執行到 findName() 產生錯誤,之後我上網搜尋 binary tree segmentation fault 找到了 [stackoverflow]( https://stackoverflow.com/questions/23767937/c-segmentation-fault-in-insert-to-binary-tree) 發現裏面有<s>雙重指標</s>指標的指標 >> 中文的「雙」表示對等的兩者,比方說「雙人」,但 `node **tree` 本質上是「指標的指標」,貿然稱為「雙指標」的話,你會發現對價關係錯誤了,請務必留意。 [name="jserv"] ```clike void addNode(double value, node **tree) { // search first while (*tree) { if (value < (*tree)->key) tree = &(*tree)->left; else if((*tree)->key < value) tree = &(*tree)->right; else return; } // no match, so add *tree = malloc(sizeof(**tree)); (*tree)->key = value; (*tree)->left = (*tree)->right = NULL; // note: set to null } ``` >>我想請問關於指標,網路上查詢之後還是不太懂,為何這邊要這樣用?? >>感謝 許友綸學長的教學已了解 >> 不要貿然讀網路上資料,為何不回頭讀 [K&R C](https://en.wikipedia.org/wiki/The_C_Programming_Language) 呢? [name="jserv"] >> 謝謝老師的建議 [name=鄭安邦] ## 實驗結果 ``` Performance counter stats for './phonebook_opt' (100 runs): 39,2941 cache-misses # 64.873 % of all cache refs ( +- 0.71% ) 60,5712 cache-references ( +- 1.02% ) 2,4814,4349 instructions # 1.69 insns per cycle ( +- 0.08% ) 1,4716,5776 cycles ( +- 0.36% ) 0.075049025 seconds time elapsed ( +- 2.39% ) ``` * cache miss 下降到 64.873% ![](https://i.imgur.com/KTOczei.png) ### 討論 * append() findName() 下降 * 如果 binary tree 有實作成功 append()應該會上升,且 findName() 應該會下降更多,代表只有 struct 資料的減少影響到實驗結果 # 還要再努力 --- * [petermouse 同學的共筆](https://hackmd.io/s/B161G0qFx#) * [twzjwang 同學的共筆](https://hackmd.io/s/HJsOjpYKl) * [vic85821 同學的共筆](https://hackmd.io/s/r1B6WwQT#) * [Binary search tree](http://www.thegeekstuff.com/2013/02/c-binary-tree/) * [Binary search tree](http://www.cprogramming.com/tutorial/c/lesson18.html) --- 昨天嘗試用 binary tree 完成實驗,可是結果沒有達到所要的要求,今天發現了錯誤的地方,是因為原本的邏輯不對,造成的不是 binary tree 而是變成 pNext_left 和 pNext_right 兩個選一個串下去,想要修改缺發生了 segmentation fault >> 請問要從何資料或書籍了解 segmentation fault 的相關知識和解決方法,我查了維基百科了解了可能發生原因,和 The C program language 卻還是無法解決