學習數據結構的筆記
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;
}
運行結果:
