两个吃奶一个添下面视频_人妻第一页香蕉网_欧美xxxx少妇_妺妺窝人体色www婷婷

通過(guò)研究證明,怎么學(xué)好數(shù)據(jù)結(jié)構(gòu)?怎么入門?需要學(xué)些什么東西?鏈表是數(shù)據(jù)結(jié)構(gòu)的重要部分,學(xué)好用好鏈表,在解題的過(guò)程中,思路將更加清晰,鏈表作為數(shù)據(jù)結(jié)果的基礎(chǔ)之一,本篇將會(huì)通過(guò)圖文和代碼展示的形式系統(tǒng)的介紹。

什么是鏈表?

鏈表是一種物理存儲(chǔ)單元上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過(guò)鏈表中的指針鏈接次序?qū)崿F(xiàn)的。鏈表由一系列結(jié)點(diǎn)(鏈表中每一個(gè)元素稱為結(jié)點(diǎn))組成,結(jié)點(diǎn)可以在運(yùn)行時(shí)動(dòng)態(tài)生成。每個(gè)結(jié)點(diǎn)包括兩個(gè)部分:一個(gè)是存儲(chǔ)數(shù)據(jù)元素的數(shù)據(jù)域,另一個(gè)是存儲(chǔ)下一個(gè)結(jié)點(diǎn)地址的指針域。


順序存儲(chǔ)和鏈?zhǔn)酱鎯?chǔ)

(1)數(shù)組—順序存儲(chǔ)

數(shù)組作為一個(gè)順序儲(chǔ)存方式的數(shù)據(jù)結(jié)構(gòu),可是有大作為的,它的靈活使用為我們的程序設(shè)計(jì)帶來(lái)了大量的便利;

但數(shù)組最大的缺點(diǎn)就是我們的插入和刪除時(shí)需要移動(dòng)大量的元素,所以,很多人想到需要大量的消耗時(shí)間,以及冗余度就想放棄或?qū)で髣e的方法。

以C語(yǔ)言數(shù)組插入一個(gè)元素為例,當(dāng)我們需要在一個(gè)數(shù)組{1,2,3,4}的第1個(gè)元素后的位置插入一個(gè)’A’時(shí),我們需要做的有:

1. 將第1個(gè)元素后的整體元素后移,形成新的數(shù)組{1,2,2,3,4}

2. 再將第2個(gè)元素位置的元素替換為我們所需要的元素’A’

3. 最終形成我們的預(yù)期,這需要很多的操作喔。

數(shù)組—順序存儲(chǔ)

上圖可以看出,使用數(shù)組都有這兩大缺點(diǎn):

1. 插入刪除操作所需要移動(dòng)的元素很多,浪費(fèi)算力。

2. 必須為數(shù)組開足夠的空間,否則有溢出風(fēng)險(xiǎn)。


(2)鏈表—鏈?zhǔn)酱鎯?chǔ)

由于數(shù)組的這些缺點(diǎn),自然而然的就產(chǎn)生鏈表的思想。

鏈表通過(guò)不連續(xù)的儲(chǔ)存方式,自適應(yīng)內(nèi)存大小,以及指針的靈活使用,巧妙的簡(jiǎn)化了上述的內(nèi)容。

鏈表的基本思維是,利用結(jié)構(gòu)體的設(shè)置,額外開辟出一份內(nèi)存空間去作指針,它總是指向下一個(gè)結(jié)點(diǎn),一個(gè)個(gè)結(jié)點(diǎn)通過(guò)NEXT指針相互串聯(lián),就形成了鏈表。

鏈表—鏈?zhǔn)酱鎯?chǔ)

其中DATA為自定義的數(shù)據(jù)類型,NEXT為指向下一個(gè)鏈表結(jié)點(diǎn)的指針,通過(guò)訪問(wèn)NEXT,可以引導(dǎo)我們?nèi)ピL問(wèn)鏈表的下一個(gè)結(jié)點(diǎn)。

對(duì)于一連串的結(jié)點(diǎn)而言,就形成了鏈表如下圖:

一連串的結(jié)點(diǎn)形成鏈表

相比起數(shù)組,鏈表解決了數(shù)組不方便移動(dòng),插入,刪除元素的弊端,但相應(yīng)的,鏈表付出了更加大的內(nèi)存犧牲換來(lái)的這些功能的實(shí)現(xiàn)。


鏈表概述

包含單鏈表,雙鏈表,循環(huán)單鏈表,實(shí)際應(yīng)用中的功能不同,但實(shí)現(xiàn)方式都差不多。

鏈表概述


鏈表與數(shù)組的區(qū)別

  回憶下數(shù)組的概念 ,所謂數(shù)組,是相同數(shù)據(jù)類型的元素按一定順序排列的集合。根據(jù)概念我們可以知道數(shù)組在內(nèi)存中連續(xù),鏈表不連續(xù);由于不同的存儲(chǔ)方式導(dǎo)致數(shù)組靜態(tài)分配內(nèi)存,鏈表動(dòng)態(tài)分配內(nèi)存,數(shù)組元素在棧區(qū),鏈表元素在堆區(qū);由于數(shù)組在內(nèi)存中連續(xù),我們可以利用下標(biāo)定位,時(shí)間復(fù)雜度為O(1),鏈表定位元素時(shí)間復(fù)雜度O(n);但是由于數(shù)組的連續(xù)性數(shù)組插入或刪除元素的時(shí)間復(fù)雜度O(n),鏈表的時(shí)間復(fù)雜度O(1)??偨Y(jié)一下,數(shù)組和鏈表的區(qū)別如下:

  1. 數(shù)組靜態(tài)分配內(nèi)存,鏈表動(dòng)態(tài)分配內(nèi)存

  2. 數(shù)組在內(nèi)存中連續(xù),鏈表不連續(xù)

  3. 數(shù)組元素在棧區(qū),鏈表元素在堆區(qū)

  4. 數(shù)組利用下標(biāo)定位,時(shí)間復(fù)雜度為O(1),鏈表定位元素時(shí)間復(fù)雜度O(n);

  5. 數(shù)組插入或刪除元素的時(shí)間復(fù)雜度O(n),鏈表的時(shí)間復(fù)雜度O(1)。


C#實(shí)現(xiàn)鏈表的基本操作

以單鏈表為例,單鏈表是一種鏈?zhǔn)酱嫒〉臄?shù)據(jù)結(jié)構(gòu),鏈表中的數(shù)據(jù)是以結(jié)點(diǎn)來(lái)表示的,每個(gè)結(jié)點(diǎn)由元素和指針構(gòu)成。元素表示數(shù)據(jù)元素的映象,就是存儲(chǔ)數(shù)據(jù)的存儲(chǔ)單元;指針指示出后繼元素存儲(chǔ)位置,就是連接每個(gè)結(jié)點(diǎn)的地址數(shù)據(jù)。

以結(jié)點(diǎn)的序列表示的線性表稱作線性鏈表,也就是單鏈表,單鏈表是鏈?zhǔn)酱嫒〉慕Y(jié)構(gòu)。

public class Node<T>
{
    private T data;
    private Node<T> next;
 
    //有參構(gòu)造函數(shù)
    //主要用例實(shí)例化需要處理的節(jié)點(diǎn)用
    public Node(T item, Node<T> next)
    {
        data = item;
        this.next = next;
    }
 
    //無(wú)參構(gòu)造函數(shù),用例實(shí)例化Node節(jié)點(diǎn)
    public Node()
    {
        data = default(T);
        next = null;
    }
 
    public Node<T> Next
    {
        get { return next; }
        set { this.next = value; }
    }
 
    public T Data
    {
        get { return data; }
        set { this.data = value; }
    }
}

接下來(lái)我們來(lái)實(shí)現(xiàn)鏈表的操作,構(gòu)造一個(gè)鏈表,在構(gòu)造鏈表里我們定一個(gè)頭結(jié)點(diǎn)的對(duì)象,頭結(jié)點(diǎn)是個(gè)很有用的節(jié)點(diǎn),在后續(xù)代碼中就可以慢慢體會(huì)到

public class MyLinkList<T>
{
   public Node<T> Head { get; set; }
 
    //構(gòu)造器 
    public MyLinkList()
    {
        Head = null;
    }
}

(1)求鏈表的長(zhǎng)度,思路:從頭結(jié)點(diǎn)向后訪問(wèn),直到最后一個(gè)節(jié)點(diǎn),代碼展示:

public int Length()
 {
     var p = Head;
     int len = 0;
     while (p != null)
     {
         ++len;
         p = p.Next;
     }
     return len;
 }

(2)清空鏈表,這個(gè)就比較奧簡(jiǎn)單了,直接將頭結(jié)點(diǎn)置為null 即可,代碼展示:

public void Clear()
{
    Head = null;
}

(3)同理判斷鏈表是否為空也要用的頭結(jié)點(diǎn),代碼展示:

public bool IsEmpty()
{
    if (Head == null)
    {
        return true;
    }
    else
    {
        return false;
    }
}

(4)在鏈表的末尾添加新元素,添加新元素,需要先判斷鏈表是否為空,如果為空我們要給頭結(jié)點(diǎn)賦值,如果不為空需要修改最后一個(gè)節(jié)點(diǎn)的next指向,代碼展示:

public void Append(T item)
 {
 
     if (Head == null)
     {
         Head = new Node<T>(item, null);
         return;
     }
     var p = new Node<T>();
     p = Head;
     while (p.Next != null)
     {
         p = p.Next;
     }
     p.Next = new Node<T>(item, null);
 }

(5)在單鏈表的第i個(gè)結(jié)點(diǎn)的位置前插入一個(gè)指定結(jié)點(diǎn),首先需要找到插入的位置,然后修改相鄰節(jié)點(diǎn)的指向即可,代碼展示:

public void Insert(T item, int i)
{
 
    if (IsEmpty() || i < 1 || i > GetLength())
    {
        return;
    }
    //如果在第一個(gè)位置插入 則只需要將該節(jié)點(diǎn)的next 指向head即可
    if (i == 1)
    {
        var first = new Node<T>(item, null);
        first.Next = Head;
        Head = first;
        return;
    }
 
    var p = new Node<T>();
    p = Head;
    var left = new Node<T>();
    var right = new Node<T>();
    int j = 1;
    while (p.Next != null && j < i)
    {
        left = p;
        right = p.Next;
        ++j;
    }
    var q = new Node<T>(item, null);
    left.Next = q;
    q.Next = right;
}

(6)刪除指定節(jié)點(diǎn),先找到要?jiǎng)h除的前一個(gè)結(jié)點(diǎn),然后修改該結(jié)點(diǎn)的next指向即可。

(7)鏈表還有刪除、獲取、查找等操作,這些都相對(duì)簡(jiǎn)單,大家可以在做題中理解。


點(diǎn)贊(0)

C語(yǔ)言網(wǎng)提供由在職研發(fā)工程師或ACM藍(lán)橋杯競(jìng)賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點(diǎn)擊了解:

一點(diǎn)編程也不會(huì)寫的:零基礎(chǔ)C語(yǔ)言學(xué)練課程

解決困擾你多年的C語(yǔ)言疑難雜癥特性的C語(yǔ)言進(jìn)階課程

從零到寫出一個(gè)爬蟲的Python編程課程

只會(huì)語(yǔ)法寫不出代碼?手把手帶你寫100個(gè)編程真題的編程百練課程

信息學(xué)奧賽或C++選手的 必學(xué)C++課程

藍(lán)橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競(jìng)賽課入門課程

手把手講解近五年真題的藍(lán)橋杯輔導(dǎo)課程

Dotcpp在線編譯      (登錄可減少運(yùn)行等待時(shí)間)