1. 程式人生 > >連結串列原理詳解及其實現

連結串列原理詳解及其實現

什麼是連結串列?

連結串列,顧名思義,是一條相互連結的資料節點表。每個節點由兩部分組成:資料和指向下一個節點的指標。連結串列的基本結構如下圖所示:
連結串列結構圖
一般來說,連結串列的頭結點不存放具體的資料,所以也被稱為啞節點(dummy node)。原因在於這樣可以比較好地區分連結串列的頭結點,而且可以大大簡化連結串列的各種操作,避免很多不必要的邊界討論。

連結串列的種類

單向連結串列 雙向連結串列 迴圈連結串列 多向表(網狀表)

連結串列的優缺點

這裡的優缺點主要是和連結串列對應的另一個數據結構:陣列相比得出的。
連結串列的優點在於:
1.物理儲存單元上非連續,而且採用動態記憶體分配,能夠有效的分配和利用記憶體資源;
2.節點刪除和插入簡單,不需要記憶體空間的重組。
作為一種資料結構,連結串列必然也有讓人詬病的地方。連結串列的缺點在於:
1.不能進行索引訪問,只能從頭結點開始順序查詢;
2.資料結構較為複雜,需要大量的指標操作,容易出錯。

單向連結串列的模板類實現

筆者實現了一個單向連結串列模板類,支援了絕大部分連結串列操作。
(筆者堅信好的程式碼不必寫過多的註釋,程式碼本身即具有良好的可閱讀性)
首先需要定義連結串列節點類:

template <class T>
class Node
{
public:
    Node();
    ~Node();

    T val;
    Node *next;
};

連結串列類的定義如下:

template <class T>
class List
{
public:
    List();
    ~List();

    void isEmpty()
; void isHead(Node<T> *node); void isTail(Node<T> *node); Node<T> *getHead(); Node<T> *getTail(); Node<T> *find(T val); Node<T> *findPrevious(T val); void insert(Node<T> *node, T val); void append(T val); void remove(T val
)
; void reverse(); int size(); void clear(); void print(); private: Node<T> *_head; };

下面是具體的連結串列操作實現:
1.連結串列是否為空

template <class T>
void List<T>::isEmpty()
{
    return _head->next == NULL;
}

2.判斷節點是否為頭結點

template <class T>
void List<T>::isHead(Node<T> *node)
{
    return node == _head;
}

3.判斷節點是否為尾節點

template <class T>
void List<T>::isTail(Node<T> *node)
{
    return node->next == NULL;
}

4.獲取連結串列的頭結點

template <class T>
Node<T> *List<T>::getHead()
{
    return _head;
}

5.獲取節點的尾節點

template <class T>
Node<T> *List<T>::getTail()
{
    Node<T> *tmpNode = _head;
    while(tmpNode->next)
    {
        tmpNode = tmpNode->next;
    }
    return tmpNode;
}

6.查詢節點

template <class T>
Node<T> *List<T>::find(T val)
{
    Node<T> *tmpNode = _head->next;
    while(tmpNode)
    {
        if (tmpNode->val == val)
        {
            return tmpNode;
        }
        tmpNode = tmpNode->next;
    }
    return NULL;
}

7.查詢上一個節點

template <class T>
Node<T> *List<T>::findPrevious(T val)
{
    Node<T> *tmpNode = _head;
    while(tmpNode->next)
    {
        if (tmpNode->next->val == val)
        {
            return tmpNode;
        }
        tmpNode = tmpNode->next;
    }
    return NULL;
}

8.在指定節點之後插入新節點

template <class T>
void List<T>::insert(Node<T> *node, T val)
{
    Node<T> *tmpNode = _head->next;
    while(tmpNode)
    {
        if (tmpNode == node)
        {
            Node<T> *newNode = new Node<T>();
            newNode->val = val;
            newNode->next = tmpNode->next;
            tmpNode->next = newNode;
            return;
        }
        tmpNode = tmpNode->next;
    }
}

9.在連結串列尾部插入節點

template <class T>
void List<T>::append(T val)
{
    Node<T> *newNode = new Node<T>();
    newNode->val = val;
    Node<T> *tail = getTail();
    tail->next = newNode;
}

10.刪除節點

template <class T>
void List<T>::remove(T val)
{
    Node<T> *prevNode = findPrevious(val);

    if (prevNode)
    {
        Node<T> *tmpNode = prevNode->next;
        prevNode->next = prevNode->next->next;
        delete tmpNode;
    }
}

11.反轉連結串列

template <class T>
void List<T>::reverse()
{
    Node<T> *tmpNode = _head->next;
    Node<T> *prevNode = NULL;
    while(tmpNode)
    {
        Node<T> *nextNode = tmpNode->next;
        tmpNode->next = prevNode;
        prevNode = tmpNode;
        tmpNode = nextNode;
    }
    _head->next = prevNode;
}

12.獲取連結串列的節點數

template <class T>
int List<T>::size()
{
    Node<T> *tmpNode = _head->next;
    int n = 0;
    while(tmpNode)
    {
        tmpNode = tmpNode->next;
        n++;
    }
    return n;
}

13.刪除整個連結串列

template <class T>
void List<T>::clear()
{
    Node<T> *tmpNode = _head->next;
    while(tmpNode)
    {
        Node<T> *node = tmpNode;
        tmpNode = tmpNode->next;
        delete node;
    }
    _head->next = NULL;
}

14.列印連結串列的所有節點

template <class T>
void List<T>::print()
{
    Node<T> *tmpNode = _head->next;
    while(tmpNode)
    {
        std::cout << tmpNode->val;//型別T需要過載輸出流操作符
        <<
        tmpNode = tmpNode->next;
        if (tmpNode)
        {
            std::cout << " ";
        }
    }
    std::cout << std::endl;
}

相關推薦

連結串列原理及其實現

什麼是連結串列? 連結串列,顧名思義,是一條相互連結的資料節點表。每個節點由兩部分組成:資料和指向下一個節點的指標。連結串列的基本結構如下圖所示: 一般來說,連結串列的頭結點不存放具體的資料,所以也被稱為啞節點(dummy node)。原因在於這樣可以比

Leetcode 021 合併2個有序連結串列 思路+反思易錯 Python實現

將兩個有序連結串列合併為一個新的有序連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。 示例:輸入:1->2->4, 1->3->4 輸出:1->1->2->3->4->4 思路:這道題的思路再明顯不

Storm概念、原理及其應用(一)BaseStorm

when 結構 tails 並發數 vm 虛擬機 cif 異步 優勢 name 本文借鑒官文,添加了一些解釋和看法,其中有些理解,寫的比較粗糙,有問題的地方希望大家指出。寫這篇文章,是想把一些官文和資料中基礎、重點拿出來,能總結出便於大家理解的話語。與大多數“wordc

Skip List(跳躍表)原理實現

#include<stdio.h>  #include<stdlib.h>      #define MAX_LEVEL 10 //最大層數      //節點  typedef  struct nodeStructure  {      int key;      int value

噴泉碼的原理以及實現

      噴泉碼是一類基於圖的線性糾刪碼,在廣播方式的通訊系統中,傳送端對原始資訊進行編碼,得到源源不斷的編碼資訊並且傳送,只要接收端能正確接收到足夠的編碼資訊就可以譯出原始資料信源,反饋重傳的差錯摔

基於MeanShift的Camshift演算法原理(opencv實現,有原始碼)

基於MeanShift的Camshift演算法原理詳解(整理) 第一篇MeanShift原理和實現 1  MeanShift原理 如下圖所示:矩形視窗中的紅色點代表特徵資料點,矩形中的圓圈代表選取視窗。meanshift演算法的目的是找到含有最多特徵的視窗區域,即使圓心與概

隨機森林 演算法原理實現步驟

#include <cv.h> // opencv general include file #include <ml.h> // opencv machine learning include file #include <stdio.h>

結點對最短路徑之Floyd演算法原理實現

上兩篇部落格介紹了計算單源最短路徑的Bellman-Ford演算法和Dijkstra演算法。Bellman-Ford演算法適用於任何有向圖,即使圖中包含負環路,它還能報告此問題。Dijkstra演算法執行速度比Bellman-Ford演算法要快,但是其要求圖中不能包含負權重

Redis Sentinel實現的機制與原理

過程 正則 發送 進行 還需 生產環境 根據 stat 時間 原文:Redis Sentinel實現的機制與原理詳解序言 Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案。實際上這意味著你可以使用Sentinel模式創建一個可以不用人為幹預而應對

VRRP原理&實例說明實現路由設備的負載均衡

VRRP 負載均衡 VRRP概述:#VRRP(Virtual Router Redundancy Protocol)虛擬路由冗余協議,容錯協議,它通過把幾臺路由設備聯合組成一臺虛擬的路由設備,並通過一定的機制來保證當主機的下一跳設備出現故障時 ,可以及時將業務切換到其它設備,從而保持通訊的連續性和可靠

希爾排序超及其java實現

希爾排序雖然已經十分古老了,但其思想確實十分值得我們學習,非常的巧妙 雖然很多資料說希爾排序是叫shell的人提出來的,我個人卻十分好奇,shell的英文好意為殼的意思,感覺希爾排序的思想就像一層層的殼一樣,從內到外越來越大,當然這是我胡謅的,具體原理如下(用的一個例項進行說明的): 原理:

反射和多型實現原理

Table of Contents 反射和多型 多型 多型的定義和用法 多型的實現原理 反射 反射的實現原理 反射的應用 反射的弊端 反射和多型 這兩種技術並無直接聯絡,之所以把它們放在一起說,是因為Java提供讓我們在執行時識別物件和類的資訊,主要有

Java LinkedList的實現原理

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Java HashSet的實現原理

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C語言實現八大排序演算法及其效能之間的

概述 排序是資料結構中的重要一節,也是演算法的重要組成部分。主要分為內部排序以及外部排序,今天我們講內部排序,也就是八大排序。 插入排序 直接插入排序 演算法思想 演算

Linux : select()實現原理【轉】

https://www.cnblogs.com/sky-heaven/p/7205491.html#4119169   轉自:http://blog.csdn.net/huntinux/article/details/39289317 原文:http://blog.csdn.n

Spring Aop底層原理(利用spring後置處理器實現AOP)

寫在前面:對於一個java程式設計師來說,相信絕大多數都有這樣的面試經歷,面試官問:你知道什麼是aop嗎?談談你是怎麼理解aop的?等等諸如此類關於aop的問題。當然對於一些小白可能會一臉懵逼;對於一些工作一兩年的,可能知道,哦!aop就是面向切面變成,列印日誌啊,什麼什麼的,要是有點學

Python Web開發中,WSGI協議的作用和實現原理

首先理解下面三個概念: WSGI:全稱是Web Server Gateway Interface,WSGI不是伺服器,python模組,框架,API或者任何軟體,只是一種規範,描述web server如何與web application通訊的規範。 uwsgi:與WSGI一樣是一種協議,是uWSGI伺服器

webpack核心概念及其執行原理

* Entry: 入口, webpack執行構建的第一步將從Entry開始,可抽象成輸入 * Module: 模組,在webpcak中一切皆模組,一個模組對應一個檔案。webpack會從配置的Entry開始遞迴找出所有依賴的模組。 * Chunk: 程式碼塊,一個Chunk由多個模組組合

HashMap底層實現原理(轉載)

本文轉自:https://blog.csdn.net/caihaijiang/article/details/6280251 java中HashMap詳解 HashMap 和 HashSet 是 Java Collection Framework 的兩個重要成員,其中 HashMap 是