diff --git a/Makefile b/Makefile
index 1223411..3039791 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,10 @@
 CC ?= gcc
-CFLAGS_common ?= -Wall -std=gnu99
+CFLAGS_common ?= -Wall -g -std=gnu99
 CFLAGS_orig = -O0
 CFLAGS_opt  = -O0
+CFLAGS_hash = -O0
 
-EXEC = phonebook_orig phonebook_opt
+EXEC = phonebook_orig phonebook_opt phonebook_hash  
 all: $(EXEC)
 
 SRCS_common = main.c
@@ -15,7 +16,12 @@ phonebook_orig: $(SRCS_common) phonebook_orig.c phonebook_orig.h
 
 phonebook_opt: $(SRCS_common) phonebook_opt.c phonebook_opt.h
 	$(CC) $(CFLAGS_common) $(CFLAGS_opt) \
-		-DIMPL="\"$@.h\"" -o $@ \
+		-DOPT  -DIMPL="\"$@.h\"" -o $@ \
+		$(SRCS_common) $@.c
+
+phonebook_hash: $(SRCS_common) phonebook_hash.c phonebook_hash.h
+	$(CC) $(CFLAGS_common) $(CFLAGS_hash) \
+		-DHASH -DIMPL="\"$@.h\"" -o $@ \
 		$(SRCS_common) $@.c
 
 run: $(EXEC)
@@ -29,6 +35,9 @@ cache-test: $(EXEC)
 	perf stat --repeat 100 \
 		-e cache-misses,cache-references,instructions,cycles \
 		./phonebook_opt
+	perf stat --repeat 100 \
+		-e cache-misses,cache-references,instructions,cycles \
+		./phonebook_hash
 
 output.txt: cache-test calculate
 	./calculate
@@ -42,4 +51,4 @@ calculate: calculate.c
 .PHONY: clean
 clean:
 	$(RM) $(EXEC) *.o perf.* \
-	      	calculate orig.txt opt.txt output.txt runtime.png
+	      	calculate orig.txt opt.txt hash.txt output.txt runtime.png
diff --git a/calculate.c b/calculate.c
index 9f2d3ab..81c00c6 100644
--- a/calculate.c
+++ b/calculate.c
@@ -43,8 +43,31 @@ int main(void)
         opt_sum_a += opt_a;
         opt_sum_f += opt_f;
     }
-    fprintf(output, "append() %lf %lf\n",orig_sum_a / 100.0, opt_sum_a / 100.0);
-    fprintf(output, "findName() %lf %lf", orig_sum_f / 100.0, opt_sum_f / 100.0);
+
+    fp = fopen("hash.txt", "r");
+    if (!fp) {
+        fp = fopen("opt.txt", "r");
+        if (!fp) {
+            printf("ERROR opening input file hash1.txt\n");
+            exit(0);
+        }
+    }
+
+    double hash_sum_a = 0.0, hash_sum_f = 0.0, hash_a, hash_f;
+    for (i = 0; i < 100; i++) {
+        if (feof(fp)) {
+            printf("ERROR: You need 100 datum instead of %d\n", i);
+            printf("run 'make run' longer to get enough information\n\n");
+            exit(0);
+        }
+        fscanf(fp, "%s %s %lf %lf\n", append, find,&hash_a, &hash_f);
+        hash_sum_a += hash_a;
+        hash_sum_f += hash_f;
+    }
+
+
+    fprintf(output, "append() %lf %lf %lf\n",orig_sum_a / 100.0, opt_sum_a / 100.0, hash_sum_a/100 );
+    fprintf(output, "findName() %lf %lf %lf", orig_sum_f / 100.0, opt_sum_f / 100.0, hash_sum_f/100 );
     fclose(output);
     fclose(fp);
     return 0;
diff --git a/main.c b/main.c
index e24cb9c..c11995e 100644
--- a/main.c
+++ b/main.c
@@ -35,14 +35,17 @@ int main(int argc, char *argv[])
         printf("cannot open the file\n");
         return -1;
     }
+#if defined (HASH)
+    hashTable *ht = hashTableInitial();
+#endif
 
-    /* build the entry */
     entry *pHead, *e;
     pHead = (entry *) malloc(sizeof(entry));
     printf("size of entry : %lu bytes\n", sizeof(entry));
     e = pHead;
     e->pNext = NULL;
 
+
 #if defined(__GNUC__)
     __builtin___clear_cache((char *) pHead, (char *) pHead + sizeof(entry));
 #endif
@@ -52,7 +55,16 @@ int main(int argc, char *argv[])
             i++;
         line[i - 1] = '\0';
         i = 0;
+#if defined (HASH)
+        append(line,ht);
+#else
         e = append(line, e);
+#endif
+
+
+
+
+
     }
     clock_gettime(CLOCK_REALTIME, &end);
     cpu_time1 = diff_in_second(start, end);
@@ -62,28 +74,52 @@ int main(int argc, char *argv[])
 
     e = pHead;
 
+
     /* the givn last name to find */
     char input[MAX_LAST_NAME_SIZE] = "zyxel";
-    e = pHead;
+    // e = pHead;
+
 
+
+#if defined (HASH)
+    assert(findName(input, ht) &&
+           "Did you implement findName() in " IMPL "?");
+    assert(0 == strcmp(findName(input, ht)->lastName, "zyxel"));
+#else
     assert(findName(input, e) &&
            "Did you implement findName() in " IMPL "?");
     assert(0 == strcmp(findName(input, e)->lastName, "zyxel"));
+#endif
+
+
+
+
 
 #if defined(__GNUC__)
     __builtin___clear_cache((char *) pHead, (char *) pHead + sizeof(entry));
 #endif
     /* compute the execution time */
     clock_gettime(CLOCK_REALTIME, &start);
+
+
+#if defined (HASH)
+    findName(input, ht);
+#else
     findName(input, e);
+#endif
+
+
     clock_gettime(CLOCK_REALTIME, &end);
     cpu_time2 = diff_in_second(start, end);
 
     FILE *output;
 #if defined(OPT)
     output = fopen("opt.txt", "a");
+#elif defined(HASH)
+    output = fopen("hash.txt","a");
 #else
     output = fopen("orig.txt", "a");
+
 #endif
     fprintf(output, "append() findName() %lf %lf\n", cpu_time1, cpu_time2);
     fclose(output);
@@ -91,8 +127,14 @@ int main(int argc, char *argv[])
     printf("execution time of append() : %lf sec\n", cpu_time1);
     printf("execution time of findName() : %lf sec\n", cpu_time2);
 
+
+
+#if defined(HASH)
+    freeHashList(ht);
+#else
     if (pHead->pNext) free(pHead->pNext);
     free(pHead);
+#endif
 
     return 0;
 }
diff --git a/phonebook_hash.c b/phonebook_hash.c
new file mode 100644
index 0000000..a19d6a8
--- /dev/null
+++ b/phonebook_hash.c
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "phonebook_hash.h"
+
+/* FILL YOUR OWN IMPLEMENTATION HERE! */
+entry *findName(char lastname[], hashTable *ht)
+{
+    /* TODO: implement */
+    entry *tmp = NULL;
+    unsigned int hash = BKDRHash(lastname);
+    /*findname*/
+    while(ht->list[hash]) {
+        tmp = ht->list[hash];
+        if (strcasecmp(lastname, tmp->lastName) == 0)
+            return tmp;
+        tmp = tmp->pNext;
+    }
+    return NULL;
+}
+
+void append(char lastName[], hashTable *ht)
+{
+    entry *tmp;
+    unsigned int hash = BKDRHash(lastName);
+    tmp = (entry *) malloc(sizeof(entry));
+
+    tmp->pNext = ht->list[hash];
+    strcpy(tmp->lastName, lastName);
+    ht->list[hash]=tmp;
+}
+
+hashTable *hashTableInitial()
+{
+    hashTable *ht = NULL;
+    ht = (hashTable *)malloc(sizeof(hashTable));
+    ht->list =(entry **)malloc(sizeof(entry *)*SIZE);
+    int i =0;
+    while(i<SIZE) {
+        ht->list[i] =NULL;
+        i++;
+    }
+
+    return ht;
+}
+
+unsigned int BKDRHash(char *str)
+{
+    unsigned int seed=31;
+    unsigned int hash=0;
+    int i = 0;
+    while(i<strlen(str)) {
+        hash = hash * seed + *str++ ;
+    }
+
+    return hash % SIZE;
+}
+
+void freeHashList(hashTable *ht)
+{
+    for(int i=0; i<SIZE; i++) {
+        entry *tmp = NULL;
+        while(ht->list[i]) {
+            tmp = (ht->list[i])->pNext;
+            free(ht->list[i]);
+            ht->list[i] = tmp;
+        }
+    }
+    free(ht);
+}
+
diff --git a/phonebook_hash.h b/phonebook_hash.h
new file mode 100644
index 0000000..957f133
--- /dev/null
+++ b/phonebook_hash.h
@@ -0,0 +1,39 @@
+#ifndef _PHONEBOOK_H
+#define _PHONEBOOK_H
+#define HASH 1
+#define MAX_LAST_NAME_SIZE 16
+#define SIZE 9971
+
+typedef struct __PHONE_BOOK_DETAIL {
+    char firstName[16];
+    char email[16];
+    char phone[10];
+    char cell[10];
+    char addr1[16];
+    char addr2[16];
+    char city[16];
+    char state[2];
+    char zip[5];
+} detail;
+
+
+
+typedef struct __PHONE_BOOK_ENTRY {
+    char lastName[MAX_LAST_NAME_SIZE];
+    detail *pDetail;
+    struct __PHONE_BOOK_ENTRY *pNext;
+} entry;
+
+
+typedef struct __HASH_TABLE {
+    entry **list ;
+} hashTable;
+
+
+
+entry *findName(char lastname[], hashTable *ht);
+void append(char lastName[], hashTable *ht);
+void freeHashList(hashTable * ht);
+hashTable *hashTableInitial(void);
+unsigned int BKDRHash(char *str);
+#endif
diff --git a/phonebook_opt.c b/phonebook_opt.c
index ee92dc3..f52775f 100644
--- a/phonebook_opt.c
+++ b/phonebook_opt.c
@@ -1,15 +1,35 @@
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
 
 #include "phonebook_opt.h"
 
 /* FILL YOUR OWN IMPLEMENTATION HERE! */
 entry *findName(char lastname[], entry *pHead)
 {
-    /* TODO: implement */
+    /*original  implement */
+
+    while (pHead != NULL) {
+        if (strcasecmp(lastname, pHead->lastName) == 0)
+            return pHead;
+        pHead = pHead->pNext;
+    }
+
     return NULL;
 }
 
 entry *append(char lastName[], entry *e)
 {
-    return NULL;
+    /* allocate memory for the new entry and put lastName */
+    e->pNext = (entry *) malloc(sizeof(entry));
+    e = e->pNext;
+    strcpy(e->lastName, lastName);
+    e->pNext = NULL;
+
+    return e;
+
+
+
 }
+
diff --git a/phonebook_opt.h b/phonebook_opt.h
index f9de825..fa33ded 100644
--- a/phonebook_opt.h
+++ b/phonebook_opt.h
@@ -1,13 +1,15 @@
 #ifndef _PHONEBOOK_H
 #define _PHONEBOOK_H
-
 #define MAX_LAST_NAME_SIZE 16
 
 /* TODO: After modifying the original version, uncomment the following
  * line to set OPT properly */
-// #define OPT 1
-typedef struct __PHONE_BOOK_ENTRY {
-    char lastName[MAX_LAST_NAME_SIZE];
+/*phonebook only search lastname so we reduce the __PHONE_BOOK_ENTRY
+ *size from 136 byte to 32 byte */
+//#define OPT 1
+
+
+typedef struct __PHONE_BOOK_DETAIL {
     char firstName[16];
     char email[16];
     char phone[10];
@@ -17,6 +19,13 @@ typedef struct __PHONE_BOOK_ENTRY {
     char city[16];
     char state[2];
     char zip[5];
+} detail;
+
+
+
+typedef struct __PHONE_BOOK_ENTRY {
+    char lastName[MAX_LAST_NAME_SIZE];
+    detail *pDetail;
     struct __PHONE_BOOK_ENTRY *pNext;
 } entry;
 
diff --git a/scripts/runtime.gp b/scripts/runtime.gp
index 8ad29ca..38dff7c 100644
--- a/scripts/runtime.gp
+++ b/scripts/runtime.gp
@@ -8,4 +8,7 @@ set output 'runtime.png'
 plot [:][:0.150]'output.txt' using 2:xtic(1) with histogram title 'original', \
 '' using ($0-0.06):($2+0.001):2 with labels title ' ', \
 '' using 3:xtic(1) with histogram title 'optimized'  , \
-'' using ($0+0.3):($3+0.0015):3 with labels title ' '
+'' using 4:xtic(1) with histogram title 'hash'  , \
+'' using ($0+0.3):($3+0.0015):3 with labels title ' ', \
+'' using ($0+0.4):($4+0.0015):4 with labels title ' '
+