單鏈表的基本操作(讀取、插入、刪除)及優缺點總結
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個數據插入結點的演算法思路是:
- 宣告一個指標p指向連結串列的第一個結點,初始化j從1開始;
- 當j< i 時,遍歷連結串列,讓p的指標向後移動,不斷指向下一結點,j累加1;
- 若到連結串列末尾p為空,說明第i個元素不存在;
- 否則查詢成功,在系統中生成一個空結點s;
- 將資料元素e賦值給s->data;
- 單鏈表的插入標準語句 s->next = p->next; p->next = s;
- 返回成功。
/*初始條件:順序線性表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個數據刪除結點的演算法思路:
- 宣告一個指標p指向連結串列的第一個結點,初始化j從1開始;
- 當j< i 時,遍歷連結串列,讓p的指標向後移動,不斷指向下一結點,j累加1;
- 若到連結串列末尾p為空,說明第i個元素不存在;
- 否則查詢成功,將欲刪除的結點p-next賦值給q;
- 單鏈表的刪除標準語句 p->next = q->next;
- 將q結點中的資料賦值給e,作為返回;
- 釋放q結點;
- 返回成功。
#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:"