學習數據結構的筆記
1.在線性表的鏈式存儲中,頭指針與頭結點之間的根本區別以及頭結點與開始結點的關系:
鏈表的頭指針一般指向其第一個結點,他有標識鏈表的作用。頭結點的作用在於統一相關操作,頭結點的數據域一般沒有意義,在某些情況下可以存放鏈表長 度。如果鏈表含有頭結點,無論鏈表是 否為空,頭指針均不為空。開始結點也就是鏈表中存儲數據的第一個結點,它是頭結點后邊的第一個結點。
2.比較順序表和鏈表各自的特點:
(1)存儲分配的方式:順序表的存儲空間是靜態分配的。鏈表的存儲空間是動態分配的。
(2)存儲密度(存儲密度=結點值域所占的存儲量/結點結構所占的存儲總量):順序表存儲密度=1。鏈表<1。
(3)存取方式:順序表可以隨機存取,也可以順序存取。鏈表是順序存取的。
(4)插入刪除時移動元素的個數:順序表平均移動近一半元素。鏈表不需要移動元素,只需要修改指針。
單鏈表基本操作的C語言實現代碼:
單鏈表結點的定義:
/*👇一個單向鏈表結點的聲明,結點串在一起就是一個鏈表*/ typedef struct LinkNode { int data; //存儲的內容,簡單得用 int 演示 LinkNode* next; //如何知道下一個結點在哪里呢?可以保存下一個結點的地址 }LinkNode;
初始化:
/*👇1.鏈表的初始化*/ //LinkNode* head 指明頭結點地址,要初始化哪一個鏈表 void Init_LinkList(LinkNode* head) { head->next = NULL; //頭結點的 next 指向地址0,表示沒有內容 }
單鏈表的插入(也是建立單鏈表的過程):
/*👇2.鏈表的插入*/ //LinkNode* head 指明頭結點地址,要初始化那一個鏈表 //int e 要插入結點的內容 //int index 要插入的位置,規定從1標號。以下的代碼不對index的范圍做檢查,假定輸入的范圍都是對的。 void Insert_LinkList(LinkNode* head, int e, int index) { //由於是單向鏈表,必須找到插入位置的前驅結點,比如要插入2位置必須先找到1位置。因為有頭結點保證一定有前驅結點。 int i; LinkNode* prev, *node; prev = head; //前驅結點 for (i = 1; i < index; i++) prev = prev->next; //👆前驅結點找到 node = (LinkNode*)malloc(sizeof(LinkNode)); node->data = e; //👆為插入的結點分配內存並賦值 //👇關鍵的插入步驟 //要在prev結點和prev->next結點之間插入node,注意賦值順序,理解一下為什么一定要是這個順序 node->next = prev->next; prev->next = node; }
單鏈表的刪除:
/*👇3.鏈表的刪除*/ int Delet_LinkList(LinkNode* head, int index) { int i; LinkNode* prev, *node; prev = head; //前驅結點 for (i = 1; i < index; i++) prev = prev->next; //👆前驅結點找到 //👇關鍵的刪除步驟 node = prev->next; int e = node->data; prev->next = node->next; free(node); return e; }
按序號查找結點值:
/*👇4.按序號查找結點值*/ void IdSearch_List(LinkNode * head, int index) { int i = 1; LinkNode * prev; prev = head->next; while (i != index)////////////////////////////////////////////👈是在index范圍正確的情況下可以。注意一下。 { prev = prev->next; i++; } printf("%d", prev->data); }
按值查找表結點:
/*👇5.按值查找表結點*/ int ValueSearch_List(LinkNode * head, int e) { int i = 1; LinkNode *prev; prev = head->next; while (prev != NULL&&prev->data != e) { prev = prev->next; i++; } if (prev == NULL) { printf("該值不存在!\n"); return NULL; } else if (prev->data == e) { return i; } }
打印:
//寫個調試打印更直觀,直接看調試窗口也可以 void print_list(LinkNode* head) { for (head = head->next; head != NULL; head = head->next) printf("%d -> ", head->data); printf("\n"); }
主函數:
/*👇定義一個鏈表的頭結點,頭結點只做定位用,指明是哪個單向鏈表的開始,里面data域雖然也占用空間但用不上。*/ LinkNode List_head;
/*直接在main函數里用Insert_LinkList建表,當然也有尾插法建表(直接插head后面)*/ int main() { Init_LinkList(&List_head); //初始化一下 Insert_LinkList(&List_head, 3, 1); print_list(&List_head); Insert_LinkList(&List_head, 1, 2); print_list(&List_head); Insert_LinkList(&List_head, 6, 3); print_list(&List_head); Insert_LinkList(&List_head, 4, 4); print_list(&List_head); printf("\n"); int value = Delet_LinkList(&List_head, 1); //Delet_LinkList(&List_head, 3);//注意上面一步已經刪除了第三個位置元素,加上這一句將會再刪除一次 print_list(&List_head); printf("刪除的結點值為:%d\n", value); printf("\n"); printf("序號為2查找的結點的值為:"); IdSearch_List(&List_head, 2); printf("\n"); printf("\n");//純屬為了輸出界面看得清楚而已 int index = ValueSearch_List(&List_head, 6); printf("結點值為6的結點位置為:%d", index); printf("\n"); printf("\n"); //ValueSearch_List(&List_head, 1000);//調用看看 return 0; }
運行結果: