/* file name: heap.c */ /* 利用堆積樹(heap tree)處理會員進出資料--載入、儲存、插入、刪除、輸出 */ #include #include #define MAX 100 /* 設定上限 */ void insert_f(void); /* 插入函數 */ void delete_f(void); /* 刪除函數 */ void display_f(void); /* 輸出函數 */ void create(int); /* 建立資料於堆積樹 */ void removes(int); /* 從堆積樹中刪除資料 */ void show(char); /* 印出資料於螢幕 */ void adjust_u(int [], int); /* 從下而上調整資料 */ void adjust_d(int [], int, int); /* 從上而下調整資料 */ void exchange(int *, int *); /* 交換資料 */ int search(int); /* 搜尋資料 */ void flushBuffer(void); int heap_tree[MAX]; /* 堆積樹陣列 */ int last_index = 0; /* 最後一筆資料的INDEX */ int main(void) { char option; do { printf("\n ******************\n"); printf(" <1> login\n"); printf(" <2> logout\n"); printf(" <3> show\n"); printf(" <4> quit\n"); printf(" ******************\n"); printf(" Enter your choice: "); option = getchar(); flushBuffer(); printf("\n"); switch(option) { case '1': insert_f(); break; case '2': delete_f(); break; case '3': display_f(); break; case '4': exit(0); default : puts("選項錯誤!"); } } while(option != '4'); return 0; } void insert_f(void) { int id_temp; if (last_index >= MAX) { /* 資料數超過上限,顯示錯誤訊息 */ printf("\n Login members are more than %d!!\n", MAX); printf(" Please wait for a minute!!\n"); } else { printf("\n Enter login ID number: "); scanf("%d", &id_temp); flushBuffer(); create(id_temp); /* 建立堆積 */ printf(" Login successfully!!\n"); } } void delete_f(void) { int id_temp, del_index; if (last_index < 1) { /* 無資料存在,顯示錯誤訊息 */ printf("\n No member to logout!!\n"); printf(" Please check again!!\n"); } else { printf("\n Enter logout ID number: "); scanf("%d", &id_temp); flushBuffer(); del_index = search(id_temp); /* 尋找欲刪除資料 */ if (del_index == 0) /* 沒找到資料,顯示錯誤訊息 */ printf(" %d not found!!\n", id_temp); else { removes(del_index); /* 刪除資料,並調整堆積樹 */ printf(" %d is logout!!\n", id_temp); } } } void display_f(void) { char option; if (last_index < 1) /* 無資料存在,顯示錯誤訊息 */ printf("\n 堆積中無資料!\n"); else { printf("\n ****************\n"); printf(" <1> increase\n"); /* 選擇第一項為由小到大排列 */ printf(" <2> decrease\n"); /* 選擇第二項為由大到小排列 */ printf(" ******************\n"); do { printf(" 請選擇: "); option = getchar(); flushBuffer(); printf("\n"); } while(option != '1' && option != '2'); show(option); } } void create(int id_temp) /* ID_TEMP為新增資料 */ { heap_tree[++last_index] = id_temp; /* 將資料新增於最後 */ adjust_u(heap_tree, last_index); /* 調整新增資料 */ } void removes(int index_temp) /* INDEX_TEMP為欲刪除資料之INDEX */ { /* 以最後一筆資料代替刪除資料 */ heap_tree[index_temp] = heap_tree[last_index]; heap_tree[last_index--] = 0; if (last_index > 1) { /* 當資料筆數大於1筆,則做調整 */ /* 當替代資料大於其PARENT NODE,則往上調整 */ if(heap_tree[index_temp] > heap_tree[index_temp / 2] && index_temp > 1) adjust_u(heap_tree, index_temp); else /* 替代資料小於其CHILDEN NODE,則往下調整 */ adjust_d(heap_tree, index_temp, last_index-1); } } void show(char op) { int heap_temp[MAX+1]; int c_index; /* 將堆積樹資料複製到另一個陣列作排序工作 */ for (c_index = 1; c_index <= last_index; c_index++) heap_temp[c_index] = heap_tree[c_index]; /* 將陣列調整為由小到大排列 */ for (c_index = last_index-1; c_index > 0; c_index--) { exchange(&heap_temp[1], &heap_temp[c_index+1]); adjust_d(heap_temp, 1, c_index); } printf("\n ID number\n"); printf(" =====================\n"); /* 選擇第一種方式輸出,以遞增方式輸出--使用堆疊 選擇第二種方式輸出,以遞減方式輸出--使用佇列 */ switch(op) { case '1': for(c_index = 1; c_index <= last_index; c_index++) printf("%14d\n", heap_temp[c_index]); break; case '2': for(c_index = last_index; c_index > 0; c_index--) printf("%14d\n", heap_temp[c_index]); break; } printf(" =====================\n"); printf(" Total member: %d\n", last_index); } void adjust_u(int temp[], int index) /* INDEX為目前資料在陣列之INDEX */ { while (index > 1) { /* 將資料往上調整至根為止 */ if(temp[index] <= temp[index/2]) /* 資料調整完畢就跳出,否則交換資料 */ break; else exchange(&temp[index], &temp[index/2]); index /= 2; } } /* INDEX1為目前資料在陣列之INDEX,INDEX2為最後一筆資料在陣列之INDEX */ void adjust_d(int temp[], int index1, int index2) { /* ID_TEMP記錄目前資料,INDEX_TEMP則是目前資料之CHILDEN NODE的INDEX */ int id_temp, index_temp; id_temp = temp[index1]; index_temp = index1 * 2; /* 當比較資料之INDEX不大於最後一筆資料之INDEX,則繼續比較 */ while (index_temp <= index2) { if ((index_temp < index2) && (temp[index_temp] < temp[index_temp+1])) index_temp++; /* INDEX_TEMP記錄目前資料之CHILDEN NODE中較大者 */ if (id_temp >= temp[index_temp]) /* 比較完畢則跳出,否則交換資料 */ break; else { temp[index_temp/2] = temp[index_temp]; index_temp *= 2; } } temp[index_temp/2] = id_temp; } /* 交換傳來之 ID1 及 ID2 儲存之資料 */ void exchange(int *id1, int *id2) { int id_temp; id_temp = *id1; *id1 = *id2; *id2 = id_temp; } int search(int id_temp) /* 尋找陣列中ID_TEMP所在 */ { int c_index; for (c_index = 1; c_index <= MAX; c_index++) if (id_temp == heap_tree[c_index]) return c_index; /* 找到則回傳資料在陣列中之INDEX */ return 0; /* 沒找到則回傳0 */ } /* 清空緩衝區 */ void flushBuffer() { while (getchar() != '\n') continue; }