※ 優點 -> 使用容易
※ 缺點 -> (1)刪除與插入造成資料移動頻繁
(2)浪費不必要之記憶體
(3)陣列長度為常數,可能不夠用
#include<stdio.h> struct student { int math; int eng; int comp; }; typedef struct student student; int main(){ student s[5]; int sum[3] = {0}; int i; int n = 0; int op,qid; while(1){ puts("(1) 新增一位同學資料"); puts("(2) 查詢某位同學成績 (輸入座號)"); puts("(3) 修改某位同學成績 (輸入座號)"); puts("(4) 列出所有資料"); puts("(5) 計算各科平均"); puts("(6) 計算某位同學成績平均 (輸入座號)"); puts("(0) 離開"); scanf("%d", &op); switch(op) { case 1: scanf("%d", &s[n].math); scanf("%d", &s[n].eng); scanf("%d", &s[n].comp); n++; break; case 2: scanf("%d", &qid); if(qid>0 && qid<=n) { printf("%d\n", s[qid-1].math); printf("%d\n", s[qid-1].eng); printf("%d\n", s[qid-1].comp); } else { printf("無此座號\n"); } break; case 3: scanf("%d", &qid); if(qid>0 && qid<=n) { scanf("%d\n", &s[qid-1].math); scanf("%d\n", &s[qid-1].eng); scanf("%d\n", &s[qid-1].comp); } else { printf("無此座號\n"); } break;case 4: for(i=0; i<n; i++){ printf("%d\n", s[i].math); printf("%d\n", s[i].eng); printf("%d\n", s[i].comp); } break; case 5: //算各科總分 for(i=0;i<n;i++){ sum[0] += s[i].math; sum[1] += s[i].eng; sum[2] += s[i].comp; } for(i=0;i<3;i++){ printf("%.2f\n", (double)sum[i]/n); } break; case 6: scanf("%d", &qid); if(qid>0 && qid<=n) { printf("%.2f\n", (double)(s[qid-1].math + s[qid-1].eng + s[qid-1].comp)/3); } else { printf("無此座號\n"); } break; case 0: return 0; break; } } return 0; }
鏈結串列
節點:鏈結串列中最基本的單位
節點 = 資料 + 結構指標
◎ 定義鏈結串列節點結構
鏈結串列透過儲存元素在記憶體之位址為指標(Pointer)或鏈結(Link)取得下一個節點。
定義節點結構:
head : 指向串列前端之指標
◎ 連續鏈結串列
node *head, *ptr;
head = (node *)malloc(sizeof(node));
ptr = head;
int value;
scanf("%d", &value);
ptr->data = value;
ptr->next = (node
*)malloc(sizeof(node));
ptr = ptr->next;
★ 新增節點
在新增節點時,最好是使用動態配置一節點之記憶體。
node *getnode () /* 此函數產生一個新節點 */ { node *p; p = (node *) malloc(sizeof(node)); /* malloc 會動態地配置大小為sizeof 的記憶體*/ /* sizeof 會傳回一個型態為node之值*/ if ( p == NULL) { printf ("記憶體不足"); exit(1); } return(p); }
★ 釋放節點
當然在使用完畢記得歸還一個節點之記憶體。
void freenode (node *p) /* 此函數將節點還給記憶體 */ { free(p); }
★ 插入節點
由鏈結串列加入一個節點,一個節點插入有三種情況:
◆ 節點加於第一個節點之前
head = (node *)malloc(sizeof(node));
head -> next = ptr;
ptr = head;
◆ 節點加於最後一個節點之後
ptr
ptr->next = (node *)malloc(sizeof(node));
ptr = ptr->next;
◆ 加於節點中間任何一個位置
node *new_node; //(1)
new_node = getnode(); //(2)
new_node->next = ptr->next; //(3)
/* 新節點指向下一節點*/
ptr->next = new_node; //(4)
/* 節點ptr指向新節點*/
node *insert_node (node *head, node *ptr, node data) { node *new_node; /* 新節點指標變數 */ new_node = getnode(); /* 建立新節點,取得一個可用節點 */ *new_node = data; /* 建立節點內容 */ new_node->next = NULL; /* 設定指標初值 */ if ( ptr == NULL ) /* 指標ptr是否是NULL */ { /* 第一種情況: 插入第一個節點 */ new_node->next = head; /* 新節點成為串列開始 */ head = new_node; } else { if ( ptr->next == NULL ) /* 是否是串列結束 */ /* 第二種情況: 插入最後一個節點 */ ptr->next = new_node; /* 最後指向新節點 */ else { /* 第三種情況: 插入成為中間節點 */ new_node->next = ptr->next; /* (3) 新節點指向下一節點 (3)*/ ptr->next = new_node; /* 節點ptr指向新節點 (4)*/ } } return (head); }
★ 尋找節點
走訪串列,將找到節點位置回傳。
node *find_node(node *head, int num) { node *ptr; ptr = head; /* 指向串列起始 */ while ( ptr != NULL ) /* 走訪串列 */ { if ( ptr->data == num ) /* 找尋data */ return (ptr); ptr = ptr->next; /* 指向下一節點 */ } return (ptr); }
★ 刪除節點
由鏈結串列中刪除一個節點,一個節點刪除有三重情況:
◆ 刪除第一個節點
head = head->next;
freenode(ptr);
return(head); /* reset 起始節點指標 */
◆ 刪除最後一個節點
ptr
previous = head;
while ( previous->next != ptr ) /* 找節點ptr的前節點 */
previous = previous->next;
previous->next = NULL; /* 最後一個節點 */
freenode(ptr); /* 此函數將節點歸還給記憶體 */
◆ 刪除中間任何一個節點
previous = head;
while ( previous->next != ptr ) /* 找節點ptr的前節點 */
previous = previous->next;
/* 第三種情況: 刪除中間節點 */
previous->next = ptr->next; //(1)
freenode(ptr); //(2) /* 此函數將節點歸還給記憶體 */
/* * 使用鏈結串列製作一個 會員資料表功能 * ‧輸入’i’ 新增節點在串列最後,可輸入姓名, 電話, Email * ‧輸入’d’接著輸入姓名,可將節點中之姓名相同者刪除(假設輸入之姓名不會重覆) * ‧輸入’f’接著輸入一個姓名,可將節點中之姓名相同者印出資料 * ‧輸入’l’ 印出串列所有節點內容並顯示目前人數 * ‧輸入’q’ 離開程式 * * 提示: 使用strcmp來實作 (string.h ) * strcmp(data[0], data[0]) * 第一個字串大於第二個字串回傳正值,反之回傳負值。相等則為0 * ※bonus:可設計插入位置於最前/中間/最後 */ #include <stdlib.h> #include <stdio.h> #include <string.h> struct _node{ int data; char name[80]; int phone; char email[80]; struct _node *next; }; typedef struct _node node; node *getnode(){ node *p; p = (node *) malloc(sizeof(node)); if(p == NULL){ printf ("記憶體不足"); exit(1); } return(p); } void freenode (node *p){ free(p); } node *insert_node (node *head, node *ptr, node data){ node *new_node; new_node = getnode(); *new_node = data; /* 建立節點內容 */ new_node->next = NULL; /* 設定指標初值 */ if (ptr == NULL) { new_node->next = head; /* 新節點成為串列開始 */ head = new_node; } else{ if (ptr->next == NULL) ptr->next = new_node; /*插入最後一個節點 */ else{ new_node->next = ptr->next; /*插入成為中間節點 */ ptr->next = new_node; } } return (head); } node *find_node(node *head, char name[]){ node *ptr; ptr = head; while (ptr != NULL){ if (strcmp(ptr->name ,name)== 0) return (ptr); ptr = ptr->next; } return (ptr); } node *delete_node(node *head, node *ptr){ node *previous; if (ptr == head) head = head->next; /*刪除第一個節點 */ else{ previous = head; while (previous->next != ptr) previous = previous->next; if (ptr->next == NULL) previous->next = NULL; /*刪除最後一個節點 */ else previous->next = ptr->next; /*刪除中間節點 */ } freenode(ptr); return(head); } int length (node *head){ int num=0; node *q = head; while (q != NULL) { num ++; q = q->next; } return(num); } int main() { node *head, *ptr, input; head = NULL; int value; char name[80]; char key; while(1){ puts("i insert at last"); puts("d delete"); puts("f find"); puts("q exit"); puts("g length"); puts("l list all data"); scanf(" %c", &key); switch(key) { case 'i': scanf("%s", input.name); scanf("%s", input.email); scanf("%d", &input.phone); if(head==NULL) head = insert_node (head, NULL, input); else{ ptr = head; while(ptr->next!=NULL) ptr = ptr->next; head = insert_node (head, ptr, input); } break; case 'd': scanf("%s", name); ptr = find_node(head, name); if(ptr==NULL) printf("Can not delete\n"); else{ head = delete_node(head, ptr); printf("Delete ok\n"); } break; case 'f': scanf("%s", name); ptr = find_node(head, name); if(ptr==NULL) printf("Not found\n"); else{ printf("found\n"); printf("%s\n", ptr->name); printf("%s\n", ptr->email); printf("%010d\n\n", ptr->phone); } break; case 'g': printf("%d\n", length(head) ); break; case 'l': ptr = head; while(ptr!=NULL){ printf("%s\n", ptr->name); printf("%s\n", ptr->email); printf("%010d\n\n", ptr->phone); ptr = ptr->next; } break; case 'q': return 0; break; } system("pause"); system("cls"); } return 0; }