220 lines
6.4 KiB
Plaintext
220 lines
6.4 KiB
Plaintext
/* file name: heap.c */
|
||
/* 利用堆積樹(heap tree)處理會員進出資料--載入、儲存、插入、刪除、輸出 */
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#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;
|
||
}
|