什么是抽象數據類型?
首先,這一概念是軟件開發人員在力求編寫的代碼健壯、易維護且可以復用的過程中產生的。
英文是AbstractData Type。有人將其比作“抽象”的牆壁,“它將接口和實現明確分開,所以用戶只看到接口,因此不需要參與實現。”構建者則着力實現ADT接口。ADT成為了雙方的契約,這使得代碼更容易維護。
接口:接口是把公共的方法和屬性組合起來以封裝特定功能的一個集合。
創建linked list.h頭文件
1 #ifndef LIST_H_ 2 #define LIST_H_ 3 #include <stdbool.h> 4 #define TSIZE 45 5 6 typedef struct book{ // 建立包含元素屬性的item結構體 7 char title[TSIZE]; 8 int rating; 9 }Item; 10 11 typedef struct node { // 鏈表的節點,包含item各項屬性以及一個用來存放下一項地址的指針(鏈表鏈接的關鍵) 12 Item item; 13 struct node*next; 14 }Node; 15 typedef Node * List; 16 17 void InitList(List * plist); 18 bool ListisEmpty(const List * plist); 19 bool ListisFull(const List * plist); 20 unsigned int ListItemCount(const List * plist); 21 bool AddItem(Item item, List * plist); 22 void Traverse(const List * plist, void(*pfun)(Item item)); 23 void EmptyTheList(List * plist); 24 25 #endif
功能函數的定義
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "list.h" 4 static void CopyToNode(Item item, Node * pnode) // 拷貝數據 5 { 6 pnode->item = item; 7 } 8 void InitList(List * plist) // 初始化鏈表為空 9 { 10 *plist = NULL; 11 } 12 13 bool ListisEmpty(const List * plist) // 檢查鏈表是否為空 14 { 15 return *plist == NULL ? true : false; 16 } 17 bool ListisFull(const List * plist) // 檢查鏈表是否已滿 18 { 19 Node * pt; 20 pt = (Node *)malloc(sizeof(Node)); 21 return pt == NULL ? true : false; 22 } 23 unsigned int ListItemCount(const List * plist) 24 { 25 unsigned int count = 0; 26 Node * pnode = *plist; 27 while (pnode != NULL) 28 { 29 ++count; 30 pnode = pnode->next; 31 } 32 return count; 33 } 34 bool AddItem(Item item, List * plist) // 在鏈表結尾添加新的項 35 { 36 Node * pnew; // 申請一個新的節點 37 Node * scan = *plist; 38 pnew = (Node *)malloc(sizeof(Node)); // 給新節點申請空間 39 if (pnew == NULL) return false; // 申請失敗,返回false 40 CopyToNode(item, pnew); // 把item的內容復制到新節點中 41 pnew->next = NULL; // 將新節點的next指針設置為NULL,表示這一節點為當前的末尾項 42 if (scan == NULL) // 如果當前是空表,則將新節點設置為表的首項 43 *plist = pnew; 44 else 45 { 46 while (scan->next != NULL) //找到當前表中的末尾節點 47 scan = scan->next; 48 scan->next = pnew; //將新節點的地址保存在末尾節點的next成員里(即給鏈表添加了一個新的項) 49 } 50 return true; 51 } 52 void Traverse(const List * plist, void(*pfun)(Item item)) // 將某函數作用於鏈表的每一節點 53 { 54 Node * pnode = *plist; // 將節點指向開頭 55 while (pnode != NULL) 56 { 57 (*pfun)(pnode->item); 58 pnode = pnode->next; 59 } 60 } 61 void EmptyTheList(List * plist) // 清空鏈表 62 { 63 Node * psave; // 用來保存當前清除項的下一節點的地址 64 while (*plist != NULL) 65 { 66 psave = (*plist)->next; 67 free(*plist); 68 *plist = psave; 69 } 70 }
用戶接口:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "list.h" 5 void showmovies(Item item); 6 char * s_gets(char * st, int n); 7 8 int main(void) 9 { 10 List book; 11 Item temp; 12 13 InitList(&book); 14 if (ListisFull(&book)) 15 { 16 fprintf(stderr, "No memory available\n"); 17 exit(EXIT_FAILURE); 18 } 19 20 puts("Enter first book title:"); 21 while (s_gets(temp.title, TSIZE) != NULL&& 22 temp.title[0] != '\0') 23 { 24 puts("Enter your rating<0-10>:"); 25 scanf("%d", &temp.rating); 26 while (getchar() != '\n') 27 continue; 28 if (AddItem(temp, &book) == false) 29 { 30 fprintf(stderr, "Problem allocating memory\n"); 31 break; 32 } 33 if (ListisFull(&book)) 34 { 35 puts("The list is now full.\n"); 36 break; 37 } 38 puts("Enter next book title(empty line to stop):"); 39 } 40 41 if (ListisEmpty(&book)) 42 printf("No data entered.\n"); 43 else { 44 printf("Here is the movies list:\n"); 45 Traverse(&book, showmovies); 46 } 47 printf("You entered %d movies.\n", ListItemCount(&book)); 48 49 EmptyTheList(&book); 50 printf("Bye\n"); 51 52 return 0; 53 } 54 void showmovies(Item item) 55 { 56 printf("book: %s Rating:%d\n", item.title, item.rating); 57 } 58 char * s_gets(char * st, int n) 59 { 60 char * ret_val; 61 char * find; 62 ret_val = fgets(st, n, stdin); 63 if (ret_val) 64 { 65 find = strchr(st, '\n'); 66 if (find) 67 *find = '\0'; 68 else 69 while (getchar() != '\n') 70 continue; 71 } 72 return ret_val; 73 }