鏈表的創建、遍歷、刪除、插入和清空


一、鏈表的概念

  鏈表是一種物理存儲結構上非連續,非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。

 

 

 

二、鏈表和數組的區別:

1、數組靜態分配內存,鏈表動態分配內存。

2、數組在內存中是連續的,鏈表是不連續的。

3、數組利用下標定位,查找的時間復雜度是O(1),鏈表通過遍歷定位元素,查找的時間復雜度是O(N)。

4、數組插入和刪除需要移動其他元素,時間復雜度是O(N),鏈表的插入或刪除不需要移動其他元素,時間復雜度是O(1)。

 

數組的優點

1、隨機訪問性比較強,可以通過下標進行快速定位。

2、查找速度快

數組的缺點

1、插入和刪除的效率低,需要移動其他元素。

2、會造成內存的浪費,因為內存是連續的,所以在申請數組的時候就必須規定七內存的大小,如果不合適,就會造成內存的浪費。

3、內存空間要求高,創建一個數組,必須要有足夠的連續內存空間。

4、數組的大小是固定的,在創建數組的時候就已經規定好,不能動態拓展。

 

鏈表的優點

1、插入和刪除的效率高,只需要改變指針的指向就可以進行插入和刪除。

2、內存利用率高,不會浪費內存,可以使用內存中細小的不連續的空間,只有在需要的時候才去創建空間。大小不固定,拓展很靈活。

鏈表的缺點

查找的效率低,因為鏈表是從第一個節點向后遍歷查找。

 

單鏈表和雙鏈表

 

 

 

三、鏈表環問題

判斷是否有環

  定義一個快指針和一個慢指針,快指針一次走兩步,慢指針一次走兩步,會出現兩種情況,情況一指針走到了空的位置,那就說明這個鏈表不帶環。情況二兩個指針相遇,說明這個鏈表帶環。


獲得入環節點

  如果不考慮空間復雜度,可以使用一個map來記錄走過的節點,這個指針一直向后遍歷如果遇到空,說明這個鏈表不帶環,也就沒有入環節點,如果沒有遇到空,如果遇到第一個在map中存在的節點,就說明回到了出發點,這個節點就是環的入口節點。如果不建立額外的空間,先使用快慢指針判斷這個鏈表是否有環,如果有環將相遇節點記錄,然后一個指針從鏈表的起始位置開始一次走一步,另一個指針從記錄的節點開始一次走一步,當兩個節點再次相遇,這個相遇節點就是環的入口節點。

 

 

 

以上轉載自https://blog.csdn.net/Shuffle_Ts/article/details/95055467

 

四、鏈表的使用

1、鏈表的創建(頭插法、尾插法)

#include<iostream>
#include<stdlib.h>
using namespace std;
struct node
{
    int x;
    node* next;//指向結構體的一個指針
};

node *Head, *End;

void add(int m)
{
    node *temp = (struct node*)malloc(sizeof(struct node));//強制類型轉換+分配地址空間

    //節點賦值,m是一個整數型的值,要把它變成結構體類型才能放進鏈表里
    temp->x = m;
    temp->next = NULL;

    if (Head== NULL)//頭指針為空,說明鏈表為空,那么temp即是頭指針,也是尾指針
    {
        Head = temp;
        End = temp;
    }
    else
    {
        //鏈表不為空的情況,讓尾指針指向當前節點,同時尾指針后移,為下一次添加節點准備
        End->next = temp;
        End = temp;

        //上面的是尾插,即在鏈表尾部加入節點
        //如果在鏈表頭部加入節點,讓頭指針指向當前節點,同時頭指針前移就可以

        //Head->next=temp;
        //Head=temp;
    }


}
int main()
{
    Head = (struct node*)malloc(sizeof(struct node));
    End = (struct node *)malloc(sizeof(struct node));
    Head->next = NULL;
    End = Head;
    int n, m;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>m;
        add(m);
    }
    node *temp = Head;
    while (temp->next!=NULL)//鏈表的遍歷
    {
        temp = temp->next;
        cout << temp->x << ' ';
    }
    cout<<endl;
    return 0;
}

 

#include<iostream>
#include<stdlib.h>
using namespace std;
struct node
{
    int x;
    node* next;//指向結構體的一個指針
};

node *Head, *End;

int main()
{
    Head = (struct node*)malloc(sizeof(struct node));
    End = (struct node *)malloc(sizeof(struct node));
    End = Head;
    int n, m;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>m;
        node *temp=(struct node*)malloc(sizeof(struct node));
        temp->x=m;
        temp->next=NULL;
        End->next=temp;
        End=temp;
    }
    node *temp = Head;
    while (temp->next!=NULL)//鏈表的遍歷
    {
        temp = temp->next;
        cout << temp->x << ' ';
    }
    cout<<endl;
    return 0;
}

 

2、鏈表的刪除、插入和清空

 

 

void clear()//清空鏈表
{
    node *now=Head;
    while(now!=NULL)
    {
        node *temp=now;
        now=now->next;
        free(temp);
    }
    Head=NULL;
    End=NULL;
}
void insert(int pos,int num)//在第pos個位置增加一個節點
{
    node *now=Head;
    for(int i=0;i<pos-1;i++)
        now=now->next;

    node *temp=(struct node*)malloc(sizeof(struct node));//創建一個新節點保存數字num
    temp->x=num;
    temp->next=now->next;
    now->next=temp;
}

void del(int num)//在鏈表中刪除數據域為num的節點
{
    node *now=Head;
    while(now->next!=NULL)
    {
        node *temp=now;//保存num所在節點的前一個節點
        now=now->next;
        if(now->x==num)
        {
            temp->next=now->next;
            free(now);
            now=temp;
        }

    }
}

 

 

完整代碼

#include<iostream>
#include<stdlib.h>
using namespace std;
struct node
{
    int x;
    node* next;//指向結構體的一個指針
};

node *Head, *End;

void add(int m)
{
    node *temp = (struct node*)malloc(sizeof(struct node));//強制類型轉換+分配地址空間

    //節點賦值,m是一個整數型的值,要把它變成結構體類型才能放進鏈表里
    temp->x = m;
    temp->next = NULL;

    if (Head== NULL)//頭指針為空,說明鏈表為空,那么temp即是頭指針,也是尾指針
    {
        Head = temp;
        End = temp;
    }
    else
    {
        //鏈表不為空的情況,讓尾指針指向當前節點,同時尾指針后移,為下一次添加節點准備
        End->next = temp;
        End = temp;

        //上面的是尾插,即在鏈表尾部加入節點
        //如果在鏈表頭部加入節點,讓頭指針指向當前節點,同時頭指針前移就可以

        //Head->next=temp;
        //Head=temp;
    }


}
void clear()//清空鏈表
{
    node *now=Head;
    while(now!=NULL)
    {
        node *temp=now;
        now=now->next;
        free(temp);
    }
    Head=NULL;
    End=NULL;
}
void insert(int pos,int num)//在第pos個位置增加一個節點
{
    node *now=Head;
    for(int i=0;i<pos-1;i++)
        now=now->next;

    node *temp=(struct node*)malloc(sizeof(struct node));//創建一個新節點保存數字num
    temp->x=num;
    temp->next=now->next;
    now->next=temp;
}

void del(int num)//在鏈表中刪除數據域為num的節點
{
    node *now=Head;
    while(now->next!=NULL)
    {
        node *temp=now;//保存num所在節點的前一個節點
        now=now->next;
        if(now->x==num)
        {
            temp->next=now->next;
            free(now);
            now=temp;
        }

    }
}

int main()
{
    Head = (struct node*)malloc(sizeof(struct node));
    End = (struct node *)malloc(sizeof(struct node));
    Head->next = NULL;
    End = Head;
    int n, m;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>m;
        add(m);
    }
    del(2);
    del(3);
    node *temp = Head;
    while (temp->next!=NULL)//鏈表的遍歷
    {
        temp = temp->next;
        cout << temp->x << ' ';
    }
    cout<<endl;
   
    return 0;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM