1. 程式人生 > >單鏈表的基本操作(讀取、插入、刪除)及優缺點總結

單鏈表的基本操作(讀取、插入、刪除)及優缺點總結

1.單鏈表的讀取

獲取連結串列第i個數據的演算法思路:
1. 宣告一個指標p指向連結串列的第一個結點,初始化j從1開始;
2. 當j< i 時,遍歷連結串列,讓p的指標向後移動,不斷指向下一結點,j累加1;
3. 若到連結串列末尾p為空,說明第i個元素不存在;
4. 否則查詢成功,返回結點p的資料。

/*初始條件:順序線性表L已存在,1≤i≤ListLength(L)*/
/*操作結果: 用e返回L中第i個數據元素的值*/
Status GetElem(LinkList L,int i ,ElemType *e)
{
int j;
LinkList p; /*宣告一指標p*/
p = L->
next; /*讓p指向連結串列L的第一個結點*/ j = 1; /*計數器*/ while(p && j<i) /*當p不為空或者j還沒有大於等於i時,迴圈繼續*/ { p = p->next; /*讓p指向下一個結點*/ ++j; } if (!p || j>i) return ERROR; /*第i個元素不存在*/ *e = p->data; /*取出第i個結點的資料*/ return OK; }

由於單鏈表的結構中沒有定義表長,所以不能事先知道要迴圈多少次,因此不方便用for迴圈來控制迴圈。

2.單鏈表的插入

插入過程,如下圖所示:
這裡寫圖片描述

只需讓s->next 和p->next的指標做一點改變即可。

s->next = p->next;
p->next = s; 

單鏈表第i個數據插入結點的演算法思路是:

  1. 宣告一個指標p指向連結串列的第一個結點,初始化j從1開始;
  2. 當j< i 時,遍歷連結串列,讓p的指標向後移動,不斷指向下一結點,j累加1;
  3. 若到連結串列末尾p為空,說明第i個元素不存在;
  4. 否則查詢成功,在系統中生成一個空結點s;
  5. 將資料元素e賦值給s->data;
  6. 單鏈表的插入標準語句 s->next = p->next; p->next = s;
  7. 返回成功。
/*初始條件:順序線性表L已存在,1≤i≤ListLength(L)*/
/*操作結果:在L中第i個位置之前插入新的資料元素e,L的長度加1*/
Status ListInsert(LinkList *L,int i ,ElemType e)
{
int j;
LintList p,s; 
p = *L;
j = 1;
while (p && j<i) /*尋找第i個結點*/
    {
    p = p->next;
    ++j;
    }
if (!p || j >i)
    return ERROR;  /*第i個元素不存在*/

s = (LinkList)malloc(sizeof(Node)); /*生成新的結點*/
s->data = e;
s->next = p->next;  /*將p的後繼結點賦值給s的後繼*/
p->next = s;  /*將s賦值給p的後繼*/
return OK;
}

3.單鏈表的刪除

這裡寫圖片描述

實際上就是一步,p->next = p->next->next. 用p來取代p->next;

q=p->next;
p->next = q->next;

單鏈表第i個數據刪除結點的演算法思路:

  1. 宣告一個指標p指向連結串列的第一個結點,初始化j從1開始;
  2. 當j< i 時,遍歷連結串列,讓p的指標向後移動,不斷指向下一結點,j累加1;
  3. 若到連結串列末尾p為空,說明第i個元素不存在;
  4. 否則查詢成功,將欲刪除的結點p-next賦值給q;
  5. 單鏈表的刪除標準語句 p->next = q->next;
  6. 將q結點中的資料賦值給e,作為返回;
  7. 釋放q結點;
  8. 返回成功。
#include <stdio.h>
#define ERROR 0
#define OK 1
Status ListDelete(LinkList *L,int i ,ElemType *e)
{
int j;
LinkList p,q;
p = *L;
j = 1;
while(p->next && j <i)
    {
    p = p->next;
    ++j;
    }
if(!(p->next) || j>i)
    return ERROR;
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}

對於基本的插入與刪除操作,它們其實都是兩部分組成:

1.遍歷查詢第i個結點;
2.插入和刪除結點。

4.單鏈表的整表建立

單鏈表是一種動態結構。
對於每個連結串列來說,它所佔用的空間大小和位置是不需要預先分配的。
所以建立單鏈表的過程,就是從“空表”的初始狀態,一次建立各元素結點,並插入連結串列中、

單鏈表的整表建立的演算法思路:
(頭插法)
1.宣告以指標p和計數器變數i;
2.建立一個空連結串列L;
3.讓L的頭結點的指標指向NULL;
4.迴圈:

  • 生成以新結點賦值給p
  • 隨機生成以數字賦值給p->data;
  • 將p插入到頭結點與前一新結點之間。

頭插法,示意圖:

這裡寫圖片描述

/*隨機產生n個元素的值,建立帶表頭結點的單鏈線性表L(頭插法)*/
void CreateListHead(LinkList *L, int n)
{
LinkList p;
int i;
srand(time(0));  /*當前時間種下隨機數種子*/
*L = (LinkList)malloc(sizeof(Node));
(*L) ->next = NULL;  /*建立帶頭結點的連結串列*/
for (i=0,i<n,i++)
    {
    P = (LinkList)malloc(sizeof(Node));  /*生成新結點*/
    p->data = rand()%100+1;  /*隨機生成100以內的數字*/
    p->next = (*L)->next;
    (*L)->next = p;  /*插入到表頭*/
    }
}

尾插法:把每次新結點都插在終端結點的後面

程式碼:

/*隨機產生n個元素的值,建立帶表頭結點的單鏈線性表(尾插法)*/
void CreateListTail(LinkList *L,int n)
{
LinkList p,r;
int i;
srand(time(0)); 
*L = (LinkList)malloc(sizeof(Node)) 
r =*L    /*r為指向尾部的結點*/
for(i=0;i<n;i++)
    {
    p = (Node *)malloc(sizeof(Node))  /*生成新結點*/
    p->data = rand() %100 +1;
    r->next = p;   /*將表尾終端結點的指標指向新結點*/
    r = p;  /*將當前的新結點定義為表尾終端結點*/
    }
r->next = NULL;   /*表示當前連結串列結束*/

5.單鏈表的整表刪除

當我們不打算使用這個單鏈表時候,我們需要把它銷燬,其實就是在記憶體中將它釋放掉。

思路:
1.宣告結點p和q;
2.將第一個結點賦值給p;
3.迴圈:

  • 將下一結點賦值給q;
  • 釋放p;
/*初始條件:順序線性表L已存在,操作結果:將L重置為空表*/
Status ClearList(LinkList *L)
{
LinkList p,q;
p = (*L)->next;   /*p指向第一個結點*/
while(p)  /*沒到表尾*/
    {
    q = p->next;
    free(p);
    p = q;
    }
(*L)->next = NULL;  /*頭結點指標域為空*/
return OK;
}

6.總結

單鏈表結構與順序儲存結構優缺點

時間效能

順序儲存結構: 查詢為O(1),因其是隨機存取結構;插入與刪除需要平均移動表長一半的元素,故為O(n);

單鏈表:查詢為O(n),查詢演算法的時間複雜度取決於i的位置,當i=1時,則不需要遍歷,第一個就取出資料了,而當i=n時則遍歷n-1次才可以。因此最壞情況為O(n);單鏈表在確定出某位置的指標後,插入和刪除時間僅為O(1);

空間效能

順序儲存結構:需要預分配儲存空間;

單鏈表:不需要分配儲存空間,只要有就可以分配,元素個數也不受限制。

  • 若線性表需要頻繁查詢,很少進行插入與刪除操作時,宜採用順序儲存結構;若需要頻繁插入和刪除時,宜採用單鏈表結構。
  • 當線性表中的元素個數變化較大或未知時,最好使用單鏈表。如果實現知道線性表的大致長度則使用順序儲存結構效率會高很多。

相關推薦

單鏈基本操作讀取插入刪除優缺點總結

1.單鏈表的讀取 獲取連結串列第i個數據的演算法思路: 1. 宣告一個指標p指向連結串列的第一個結點,初始化j從1開始; 2. 當j< i 時,遍歷連結串列,讓p的指標向後移動,不斷指向下一結點,j累加1; 3. 若到連結串列末尾p為空,說明第i個

單鏈 基本操作元素遞增排序

題目描述: 有一個帶頭節點的單鏈表L(至少有一個數據節點),設計一個演算法使其元素遞增有序排列。 解題思路: 由於單鏈表L中有一個以上的資料節點,首先構造一個只含有頭結點和首節點的有序單鏈表(只含有一個數據節點的單鏈表一定是有序的),然後掃描單鏈表L餘下的節點(由P指向),在有序單鏈表中

單鏈基本操作刪除連結串列中最大元素

題目描述: 設計一個演算法,刪除一個單鏈表L中元素值最大的節點(假設這樣的節點唯一) 解題思路: 在單鏈表中刪除一個節點先要找到它的前驅節點,用指標p掃描整個單鏈表,pre指向節點p的前驅節點,在掃描時用maxp指向data域值最大的節點,maxpre指向maxp所指節點的前驅節點,當連

Java單鏈基本操作--排序

單鏈表的插入排序比陣列麻煩,因為每次都都要從頭節點開始往後遍歷,頭節點也需要單獨處理 package listnode; /** * @author Gavenyeah * @date St

Java單鏈基本操作--合併兩個有序單鏈

package listnode; /** * @author Gavenyeah * @date Start_Time:2016年4月1日 下午15:01:47 * @date End_Ti

Java單鏈基本操作--刪除重複節點;

package listnode; public class DeleteDuplecate_SingleList { public static void main(String[] arg

Java單鏈基本操作--單鏈反轉

單鏈表反轉是筆試面試中考察最多的演算法之一,是單鏈表裡必須要熟練掌握的演算法。 /** * @author Gavenyeah * @date Start_Time:2016年4月1日 上午

Java單鏈基本操作--查詢倒數第K個節點

package listnode; /** * @author Gavenyeah * @date Start_Time:2016年4月1日 上午11:47:44 * @date End_Ti

無頭單鏈操作基於前面的修改版

slist.h #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<assert.h>

順序棧的基本操作入棧和出棧C語言實現詳解

棧,可以理解為遵循“後入先出”原則的線性表,因此棧結構可以採用順序表或連結串列實現。 順序棧的實現採用的是順序表,也就是陣列。 順序棧的實現思想是:在陣列中設定一個隨時指向棧頂元素的變數(一般命名為 top ),當 top 的值為 -1 時,說明陣列中沒有資料,即棧中沒有資料元素,為“空棧”;只要資料元素

鏈棧的基本操作入棧和出棧C語言實現完全攻略

鏈棧,即用線性表的連結串列結構實現棧的功能。實現過程中,鏈棧不需要建立頭結點,增加頭結點反而會增加程式的複雜性,因此連結串列中只需要建立一個頭指標就可以了。 鏈棧的實現思想是:用連結串列頭結點的一端作為棧的棧頂端,這樣做的好處是當資料元素壓棧或者彈棧時,直接使用頭指標就可以完成,不需要增設額外的指標。 例

單鏈的基礎操作頭插法尾插法插入刪除

一、連結串列的建立(頭插法和尾插法) 1、頭插法:把後建立的結點插在頭部。用這種方法建立起來的連結串列的實際順序與輸入順序剛好向反,輸出時為倒序! 下面附上程式碼: struct node *headcreat() { struct node *p,*q,*head;

C++ 單鏈表基本操作分析與實現 連結串列   連結串列是一種物理儲存單元上非連續非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列結點連結串列中每一個元素稱為結點組成,結

連結串列   連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列結點(連結串列中每一個元素稱為結點)組成,結點可以在執行時動態生成。每個結點包括兩個部分:一個是儲存資料元素的資料域,另一個是儲存下一個結點地址的指標域。 相比於線性表

單鏈 簡單題單鏈基本操作

題目描述: 有一個帶頭結點的單鏈表L=(a1,b1,a2,b2,......an,bn),設計一個演算法將其拆分成兩個帶頭結點的單鏈表L1和L2,其中L1=(a1,a2,a3...an),L2=(b1,b2,b3....bn),要求L1使用L的頭結點。 解題思路: 利用原單鏈表L中的所有

單鏈基本操作增加,查詢,刪除,修改-- C 語言

#include <stdio.h> #include <stdlib.h> typedef struct Link { // 資料域 int data; // 指標

資料結構之連結串列1單鏈基本操作

1.前言 1.1宣告 文章中的文字可能存在語法錯誤以及標點錯誤,請諒解; 如果在文章中發現程式碼錯誤或其它問題請告知,感謝! 2.關於連結串列 2.1什麼是連結串列 連結串列可以看成一種在物理儲存單元上的非連續、非順序儲存的資料結構,該資

單鏈基本操作的C語言實現鏈式儲存結構

#include<stdio.h> #include<stdlib.h> typedef int DataType; typedef struct Node{ DataType data; struct Node *next; }

資料結構c語言——線性單鏈基本操作

#include <stdio.h> #include <stdlib.h> typedef int Element; typedef char(*Status)[10]; #define ERROR "error" #define OK "ok"

C/C++學習迴圈雙鏈操作之建立,插入刪除

雙向連結串列 迴圈單鏈表的出現,雖然能夠實現從任一結點出發沿著鏈能找到其前驅結點,但時間耗費是O(n)。如果希望從表中快速確定某一個結點的前驅,另一個解決方法就是在單鏈表的每個結點裡再增加一個指向其

UFT 基本操作描述性編程函數循環

ive dial 方法 wid 基本操作 logs pan log ron 1、描述性編程 class("描述性屬性1:=值","描述性屬性2:=值") 如輸入姓名,使用對象屬性方法: Dialog("Login").WinEdit("Agent Name:"