c語言實現單鏈表
定義
首先來看一看單鏈表的定義(看看百度的)
單鏈表是一種鏈式存取的數據結構,用一組地址任意的存儲單元存放線性表中的數據元素。鏈表中的數據是以結點來表示的,每個結點的構成:元素(數據元素的映象) + 指針(指示後繼元素存儲位置),元素就是存儲數據的存儲單元,指針就是連接每個結點的地址數據。[1]
再來看看我用c語言的描述吧
typedef struct Node
{
//數據域
int data;
//指針域
struct Node *pNext;
}NODE,*PNODE;
//NODE 等價於 struct Node
//*PNODE 等價於 struct Node *
數據域:用來存放數據
指針域:用來指向下一個結點(邏輯上相連)
如果看不懂,看看圖吧:)
HEAD是頭結點
HEAD指向的是首結點
創建
創建單鏈表
思路:
我們可以一個一個的創建node最後串在一起。。。。
也可以先創建一個頭,然後創建一下一個,並把最後一個結點的pNext指向下一個,如此循環,這裏我們就要用一個指針一直指向鏈表的最後一個(尾指針),代碼就是使用的這種
PNODE Create_Node(void)
{
int len, val;
PNODE List;
PNODE pHead = (PNODE)malloc(sizeof(NODE));//分配一個頭結點
if(NULL == pHead)
{
printf("memory allocation failure");
exit(-1);
}
else
{
PNODE pTail = pHead; //尾指針指向頭
pHead->pNext = NULL;
printf("please input the length of list: ");
scanf("%d",&len); //鏈表長度
for(int i=0; i<len; i++)
{
PNODE p = (PNODE)malloc(sizeof(NODE));
if(NULL == p)
{
printf("memory allocation failure");
exit(-1);
}
else
{
printf("please input the value of list: ");
scanf("%d",&val);
//尾指針指向p
p->data=val;
pTail->pNext=p;
p->pNext=NULL;
pTail=p;
}
}
}
return pHead; //這裏返回的是頭結點 不是首結點
}
銷燬
銷燬鏈表,就是幹掉這個鏈表從頭到尾,什麼都不留
思路:
從頭開始釋放,但是把頭釋放掉之後就找不到下一個結點,所以預先把下一個結點保存下來,然後刪除,循環,有點繞,你可以簡單的理解爲過河拆橋
void destory_Node(PNODE pHead)
{
if(pHead == NULL)
return ;
PNODE temp = NULL;
while(pHead != NULL)
{
// printf("--------\n");
// print(pHead->data);
temp = pHead->pNext; // 先拿到下一個結點
free(pHead);
pHead = temp;
// if(pHead == NULL){
// printf("NULL");
// }
}
}
清空
清空結點,只留下一個頭結點,並讓它指向NULL,意思就是把數據刪了留下頭
思路:直接從首節點銷燬,把頭結點指向NULL
PNODE clear_Node(PNODE pHead)
{
if(pHead->pNext == NULL)
return pHead;
destory_Node(pHead->pNext);
pHead->pNext = NULL;
return pHead;
}
打印
循環打印 沒什麼好說的 直接上代碼
這裏寫代碼片void print(PNODE p)
{
p = p->pNext;
while(NULL != p){
printf("%d \n",p->data);
p = p->pNext;
}
}
獲取長度
注意長度是從有效節點開始的
int length_Node(PNODE pHead)
{
//這裏的長度是有效data的值 所以頭結點不算
int len = 0;
PNODE p = pHead->pNext;
while(p != NULL)
{
len++;
p = p->pNext;
}
return len;
}
查詢
思路:注意最前面有一個頭結點 所以會-1,這樣返回的就是第pos個結點了
PNODE find_Node(PNODE pHead, int pos)
{
int i = 0;
PNODE p = pHead;
while(NULL != p && i < pos-1)
{
p = p->pNext;
i++;
}
if(p->pNext == NULL || i > pos-1)
{
printf("error input pos");
exit(-1);
}
return p->pNext;
}
刪除第pos個結點
思路:第一個結點特殊處理,後面的直接在查詢的基礎上找到pos-1的結點,然後拿到pos,pos+1結點,刪掉pos,把pos-1指向pos+1
bool delete_Node_pos(PNODE pHead, int pos)
{
PNODE pre,cur,next;
if(pos == 1)
{
next = pHead->pNext;
pHead->pNext = next->pNext;
free(next);
next = NULL;
return true;
}
pre = find_Node(pHead, pos-1);
if(pre->pNext != NULL)
{
cur = pre->pNext;
next = cur->pNext;
//pos前一位 指向pos後一位
pre->pNext = next;
//釋放pos
free(cur);
cur = NULL;
return true;
}
else
{
printf("pos out of node");
}
return false;
}
在第pos插入結點
思路:重點是找到pos-1的結點,所以第一個結點特殊處理,找到前一個結點後,把他的next指向新結點,新節點指向前一個結點指向的地方
bool insert_Node(PNODE pHead, int pos, int data)
{
PNODE p = NULL;
if(pos == 1){
p = pHead;
}
else
{
//找前一位
p = find_Node(pHead,pos-1);
}
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(pNew == NULL)
{
printf("memory allocation failure");
exit(-1);
}
printf("insert %d into Node->%d \n",data,pos);
//最後結果p(pos-1)->pNew(pos)->q(pos+1原第pos結點)
pNew->data = data;
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return true;
}