1. 程式人生 > 其它 >單鏈表操作

單鏈表操作


/* 單鏈表的基本操作
單鏈表分兩種:有頭結點和無頭結點
插入單鏈表方式:頭部插入和尾部插入,不管是頭部插入還是尾部插入,步驟是:
   1) 先把新結點的next指標指向下一個結點
   2)再把前一個結點的next指向新結點
*/
#include <stdio.h>
#include <stdlib.h>

//單向連結串列資料結構
typedef struct LinkedList {
    int data;
    struct LinkedList *next; 
} LinkedList;

//初始化一個單鏈表
//頭部插入結點
LinkedList * link_list_create_from_head(int * data,int length)
{
    //建立頭結點(相當於哨兵結點,不儲存資料)並分配空間
    LinkedList *head = (LinkedList *)malloc(sizeof(LinkedList));
    if(head == NULL)
    {
        printf("申請空間失敗");
        return NULL;
    }
    //初始化連結串列為空連結串列
    head->next = NULL;

    for(int i = 0;i < length;i++)
    {
        //建立結點,並分配記憶體空間
        LinkedList *node = (LinkedList *)malloc(sizeof(LinkedList));
        //為結點資料域賦值
        node->data = data[i];
        //先將當前插入結點next指標指向下一個結點,即之前的head指標所指向的結點
        node->next = head->next;
        //然後再將頭結點的next指向當前插入結點
        head->next = node;
    }
    
    return head;
}

//初始化一個單鏈表
//尾部插入結點
LinkedList * link_list_create_from_tail(int *data,int length)
{
    LinkedList *head = (LinkedList *)malloc(sizeof(LinkedList));
    if(head == NULL){
        printf("申請空間失敗");
        return NULL;
    }
    //初始化連結串列為空
    head->next = NULL;

    //必須申明一個指向新插入結點的指標,用來標識插入新結點位置
    //開始時候p指向head結點
    LinkedList *p = head;

    for(int i=0;i<length;i++){
        LinkedList *node = (LinkedList *)malloc(sizeof(LinkedList));
        node->data = data[i];
        //由於每次插入都是最後一個,所以結點的next指標始終指向NULL
        node->next = NULL;
        //前一個結點指標就是p的next指向新結點
        p->next = node;

        //然後把指標指向新結點
        p = node;
    }
    return head;
}

//遍歷單向連結串列
//head: 傳入頭結點
void print_linkedlist(LinkedList * head)
{   
    if(head == NULL)
    {
        printf("單鏈表為空");
    }
    //由於頭結點不儲存資料,故從下一個結點遍歷資料
    //申明指標p,指向頭結點的下一結點
    LinkedList *p = head->next;
    //迴圈連結串列,直到指標p為空
    while(p)
    {
        printf("%d ",p->data);
        //指標p迴圈指向下一結點
        p = p->next;
    }
}

//單鏈表的插入,在連結串列的第i個位置插入x的元素
LinkedList * link_list_insert(LinkedList *head,int pos,int x){
    LinkedList *p = head;
    //0位置是頭結點,忽略
    //找到需要插入位置的前驅結點p
    for(int i=1;i<pos;i++){
        p = p->next;
    }
    LinkedList *node = (LinkedList *)malloc(sizeof(LinkedList));
    node->data = x;
    //新結點的next指向下一個結點,也就是前驅結點p指向的結點
    node->next = p->next;
    //想前驅結點重新指向新結點
    p->next = node;
    return head;
}

//單鏈表的刪除,在連結串列中刪除值為x的元素,每次只能刪除一個結點
LinkedList * link_list_delete(LinkedList *head,int x){
    LinkedList *p = head->next;//p指標找值為x結點
    LinkedList *pre = head;//pre指標作為x節點的前驅結點
    //while主要遍歷連結串列,找到資料為x結點的前驅結點pre
    while(p){   
        if(p->data == x){
           break; 
        }
        pre = p;
        p = p->next;
    }
    //前驅結點的next指標重新指向要刪除結點的下一個結點
    pre->next = p->next;
    //釋放p結點
    free(p);
    
    return head;
}

//單鏈表內容的修改,在連結串列中修改值為x的元素變為為k
LinkedList * link_list_update(LinkedList *head,int x,int k){
    LinkedList *p = head->next;//p指標找值為x結點
    //while主要遍歷連結串列,找到資料為x結點
    while(p){ 
        if(p->data == x){
            p->data = k;
        }
        p = p->next;
    }
    return head;
}


int main(int argc,char *argv[])
{
    int data[6] = {1,2,3,4,5,6};
    LinkedList *head = link_list_create_from_head(data,6);
    print_linkedlist(head);
    printf("\n");
    LinkedList *tail = link_list_create_from_tail(data,6);
    print_linkedlist(tail);
    printf("\n");
    //在第2個位置上插入10
    // LinkedList *L = link_list_insert(tail,2,10);
    // print_linkedlist(L);
    // printf("\n");
    //刪除data=10的結點
    LinkedList *L1 = link_list_delete(tail,6);
    print_linkedlist(L1);
    printf("\n");
    //更新data=10的結點
    // LinkedList *L2 = link_list_update(tail,4,44);
    // print_linkedlist(L2);
    return 0;
}