數據結構之單鏈表


1. 鏈表的特點

  • 鏈表是一種非線性、非順序的物理結構,是由若干個節點組成。
  • 鏈表采用的是“見縫插針”的存儲方法,不要求內存連續,靠next指針關聯起來。
  • 鏈表的物理存儲方式為隨機存儲,訪問方式為順序訪問。
  • 查找節點的時間復雜度為O(n),插入、刪除節點的時間復雜度為O(1)。
  • 鏈表適用於寫操作多,讀操作少的場景。
 1 //單向鏈表節點的數據結構
 2 struct SingleListNode
 3 {
 4     int   nData;//當前節點的數據
 5     Node* pNext;//指向下一個節點的指針
 6 };
 7 
 8 //雙向鏈表節點的數據結構
 9 struct DobuleListNode
10 {
11   int nData;//當前節點的數據
12   Node* pPre;//指向上一個節點的指針
13   Node* pNext;//指向下一個節點的指針
14 };

2. 鏈表的基本操作

鏈表的操作方式主要分為增、刪、改、查,下面以單鏈表為例,分別以最簡單的方式介紹基本用法。

首先定義一個單鏈表數據結構:

 1 struct SingleListNode
 2 {
 3     int             nVal;
 4     SingleListNode* pNext;
 5     SingleListNode():pNext(NULL){}
 6     SingleListNode(int nTempValue):nVal(nTempValue),pNext(NULL){}
 7 };
 8 
 9 class SingleList
10 {
11 public:
12     SingleList():m_pHead(NULL),m_nSize(0){}
13     ~SingleList(){}
14 public:
15     SingleListNode* Find(int nIndex);
16     void            Insert(int nIndex,SingleListNode* pNode);
17     SingleListNode* Remove(int nIndex);
18     void            PrintList();
19 private:
20     SingleListNode* m_pHead;
21     int             m_nSize;
22 };

2.1 查找

鏈表節點的查找不能通過索引快速定位,只能從頭節點開始查找。

 1 SingleListNode* SingleList::Find(int nIndex)
 2 {
 3     if(nIndex < 0 || nIndex >= m_nSize)
 4     {
 5         printf("SingleList::Find:failed! the index is out of range. index is %d \n",nIndex);
 6         return NULL;
 7     }
 8 
 9     if(NULL == m_pHead)
10     {
11         printf("SingleList::Find:failed! the head node is null. \n");
12         return NULL;
13     }
14     
15     SingleListNode* pRet = m_pHead;
16     for(int i = 0;i < nIndex;i++)
17     {
18         if(pRet)
19         {
20             pRet = pRet->pNext;
21         }
22     }
23     return pRet;
24 }

 

2.2 更新

首先從列表中查找待更新的節點,直接把舊數據替換為新值即可。

2.3 刪除

刪除分為三種情況:

  • 尾部刪除:將倒數第二個節點的next指針只為空。
  • 頭部刪除:將鏈表頭節點設為原頭節點的next指針。
  • 中間刪除:將前置節點的next指針指向待刪除節點的next指針。中間刪除和尾部刪除可以采用同一段代碼實現。
 1 SingleListNode* SingleList::Remove(int nIndex)
 2 {
 3     SingleListNode* pRet = NULL;
 4     if(nIndex < 0 || nIndex >= m_nSize)
 5     {
 6         printf("SingleList::Remove:failed! the index is out of range, size is %d .\n ",m_nSize);
 7         return pRet;
 8     }
 9 
10     if(NULL == m_pHead)
11     {
12         printf("SingleList::Remove:failed! the head node is null. \n");
13         return NULL;
14     }
15 
16     if(nIndex == 0)
17     {
18         pRet = m_pHead;
19         m_pHead = m_pHead->pNext;
20     }
21     else
22     {
23         SingleListNode* pPreNode = Find(nIndex - 1);
24         if(pPreNode == NULL)
25         {
26             printf("SingleList::Remove:failed! the pPre node is null.\n ");
27             return pRet;
28         }
29 
30         pRet = pPreNode->pNext;
31         if(pRet)
32         {
33             pPreNode->pNext = pRet->pNext;
34             m_nSize--;
35         }
36     }
37     
38     return pRet;
39 }

2.4 插入

  • 尾部插入:將尾節點的next指針指向新插入的節點。
  • 頭部插入:首先將帶插入的節點的next指針頭節點,然后將新插入的節點設為鏈表頭節點(注意順序不能反)。
  • 中間插入:首先將新節點的next指針指向插入位置的節點,然后將原始插入位置節點的前置節點的next指針指向新節點(注意順序不能反)。中間插入和尾部插入可以采用同一段代碼實現。
 1 void SingleList::Insert(int nIndex,SingleListNode* pNode)
 2 {
 3     if(NULL == pNode)
 4     {
 5         printf("SingleList::Insert:failed! the pNode is null.\n ");
 6         return;
 7     }
 8 
 9     if(nIndex < 0 || nIndex > m_nSize)
10     {
11         printf("SingleList::Insert:failed! the index is out of range, size is %d .\n ",m_nSize);
12         return;
13     }
14 
15     if(nIndex == 0)
16     {
17         //first
18         pNode->pNext = m_pHead;
19         m_pHead = pNode;
20     }
21     else
22     {
23         SingleListNode* pPre = Find(nIndex - 1);
24         if(pPre == NULL)
25         {
26             printf("SingleList::Insert:failed! the pPre node is null.\n ");
27             return;
28         }
29 
30         pNode->pNext = pPre->pNext;
31         pPre->pNext = pNode;
32     }
33     m_nSize++;
34 }

 


3. 鏈表的應用

常見的面試題中考察鏈表應用的場景有:

  • 兩數相加
  • 判斷鏈表中是否有環
  • 刪除鏈表的倒數第N個節點
  • 反轉鏈表(單鏈表)
  • 回文鏈表
  • 合並兩個有序鏈表
    等等,后邊會單獨出一篇文章介紹面試中常見的鏈表算法題。


免責聲明!

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



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