單鏈表的定義、插入和刪除

一、定義一個單鏈表
struct LNode{          //定義單鏈表節點類型ElemType data;     //存放節點數據元素struct LNode *next; //指針指向下一個結點
};
//增加一個新節點:在內存中申請一個結點所需空間,并用指針p指向這個結點
struct LNode * p =(struct LNode *)malloc(sizeof(struct LNode));

typedef 關鍵字 —— 數據類型重命名,所以上述代碼還可以寫成:

typedef struct LNode LNode; //struct LNode重命名為LNode
LNode * p =(LNode *)malloc(sizeof(LNode));

書本上的寫法

typedef struct LNode{ElemType data;struct LNode *next;
}LNode,*LinkList;/*
上述寫法與下面寫法等價
*/
struct LNode{ElemType data;struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode *LinkList;

這里有一點需要注意:
雖然LNode *和LinkList效果一樣,但是兩者的意義不一樣。

強調這是一個單鏈表——LinkList
強調這是一個結點——LNode *

在這里插入圖片描述

二、初始化一個單鏈表
1.帶頭結點

帶頭結點:頭指針指向一個節點,這個結點不存放數據,這個結點的next存放指向第一個數據的指針,這樣的節點叫頭結點。

不帶頭結點:頭指針指向的第一個節點就是數據元素結點。

在這里插入圖片描述

typedef struct LNode{ElemType data;struct LNode *next;
}LNode,*LinkList;
//初始化一個單鏈表(帶頭結點)
bool InitList(LinkList &L){L = (LNode *)malloc(sizeof(LNode));//分配一個頭結點if(L==NULL)        //內存不足,分配失敗return false;L->next = null;    //頭結點之后暫時還沒有節點return true;
}
//判斷單鏈表是否為空(帶頭結點)
bool Empty(LinkList L){if(L->next == NULL)return true;elsereturn false;
}
void test(){LinkList L; //聲明一個指向單鏈表的指針InitList(L);//初始化一個空表//......
}
2.不帶頭結點

空表判斷條件

L == NULL
三、單鏈表的插入

(一)按位序插入(帶頭結點)

typedef struct LNode{ElemType data;struct LNode *next;
}LNode,*LinkList;//在第i個位子插入元素e
bool ListInsert(LinkList &L,int i,ElemType e){if(i<1)return false;LNode *p; //p指向當前掃描到的結點int j=0;  //當前p指向的是第幾個結點p=L;      //L指向頭結點頭結點是第0個結點(不存放數據)/*因為要插入到第i個結點,所以我們只要找到第i-1個結點,然后將結點插入				到第i-1個結點即可。*/while(p!=NULL && j<i-1){ //循環到第i-1個結點p=p->next;j++;}if(p==NULL)   //i值不合法return false;LNode *s=(LNode *)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return true; //插入成功}

代碼解析:
1.j=0,以i=1為例,不滿足j<i-1,直接跳過循環。

  • 第一步,LNode *s=(LNode *)malloc(sizeof(LNode)); 開辟一塊結點內存空間;將e賦給s結點的data域:s->data = e在這里插入圖片描述
  • 第二步,改變指針指向:s->next = p->next; p->next = s;
    需要注意的是①和②的操作不能顛倒,否則就會導致s結點之后的數據丟失。
    在這里插入圖片描述
    2.j=0,以i=3為例,i-1=2j<i-1,滿足循環條件
  • 下面分析一下循環部分的代碼
    j=0j<2,執行p=p->next,滿足循環條件,p向后移動
    在這里插入圖片描述
    j++=1j<2,執行p=p->next,滿足循環條件,p向后移動
    在這里插入圖片描述
    ③j++=2,不滿足循環條件,跳出循環

之后插入的操作跟上述i=1的操作一樣

  • 開辟結點空間,并給結點空間賦值:LNode *s=(LNode *)malloc(sizeof(LNode)); s->data = e;
    在這里插入圖片描述
  • 改變指針指向:s->next = p->next; p->next = s;
    在這里插入圖片描述
    3.如果i=6,當p指向第5個結點時不滿足p!=null(即找不到第i-1個結點),會跳出循環

時間復雜度分析:

  • 插入表頭時間復雜度為 O(1)
  • 插入到表尾時間復雜度為O(n)
  • 平均時間復雜度為O(n)

(二)按位序插入(不帶頭結點)
在這里插入圖片描述

思路:跟帶頭結點一樣,找到第i-1個結點,然后把結點插入第i-1個結點之后。
需要注意的是,如果不帶頭結點,則插入、刪除第一個元素時,需要更改頭指針。

typedef struct LNode{ElemType data;struct LNode *next;
}LNode,*LinkList;
bool ListInsert(LinkList &L,int i,ElemType e){if(i==1){//插入第一個結點操作與其他結點不同LNode *s = (LNode *)malloc(sizeof(LNode));s->data = e;s->next = L;L=s; //頭指針要指向新的結點return true;}LNode *p;int j=1;//當前p指向的是第幾個結點p=L;    //p指向第一個結點,不是頭結點while(p!=NULL && j<i-1){//循環找到第i-1個結點p=p->next;j++;}if(p==NULL){return false;//i值不合法}LNode *s = (LNode *)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return true; //插入成功}

四、指定結點的插入操作

(一)指定結點的后插操作

//后插操作:在p結點之后插入元素e
bool InsertNextNode(LNode *p,ElemType e){if(p==NULL)return false;s->data = e;s->next = p->next;p->next = s;return true;
}

(二)指定結點的前插操作
思路1:如果要在p的前驅插入一個結點,那就循環查找p的前驅q,再對q后插
但是如果要找到p的前驅就要傳入頭指針。

//前插操作:在p結點之前插入元素e
bool InsertPriorNode(LinkList L,LNode *p,ElemType E){
}

時間復雜度:O(n)
思路2:
新建一個結點,讓這個結點作為p的后繼結點。然后調換一下兩個結點里的數據,這樣需要插入的數據依舊在p的前面,依然可以實現前插操作。

bool InsertPriorNode(LNode *p,ElemType e){if(p==NULL)return false;LNode *s=(LNode *)malloc(sizeof(LNode));if(s==NULL)return false;s->next=p->next; p->next=s;       //新結點s連接到p之后s->data=p->data; //p中的元素復制到s中p->data=e;       //p中存放新插入的數據ereturn true;
}

時間復雜度:O(1)

關鍵代碼圖解:

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

在這里插入圖片描述
s->data=p->data; p->data=e;
在這里插入圖片描述

五、刪除

(一)、按位序刪除

刪除表L中第i個位置的元素

思路:如果要刪除第i個元素,那么找到第i-1個元素,讓其指向第i+1個元素,再把第i個元素的空間釋放掉。

//帶頭結點
bool ListDelete(LinkList &L,int i,ElemType &e){if(i<1)return false;LNode *p;//p指向當前掃描的結點int j=0; //當前p指向的是第幾個結點p=L;     //L指向頭結點,頭結點是第0個結點(不存放數據)while(p!=NULL && j<i-1){//循環找到第i-1個結點p=p->next;j++;}if(p==NULL)   //i值不合法return false;if(p->next==NULL) //第i-1個結點之后已無其他結點return false;LNode *q=p->next; //q指向被刪除的結點e=q->data;        //用e返回被刪除的元素的值p->next=q->next;  //被刪除的結點從鏈表中斷開free(q);          //釋放結點的存儲空間return true;      //刪除成功
}

最壞、平均時間復雜度:O(n)
最好時間復雜度:O(1)

(二)、指定結點刪除

同樣的道理,如果不傳入頭指針,那就找不到指定指定結點的前驅結點。

那如果在不傳入頭指針的情況下該怎么刪除呢?我們想到一個辦法:把p的后繼結點的數據域賦給p,然后再把p的后繼結點q所指向的空間釋放掉。

//刪除指定結點p
bool DeleteNode(LNode *p){if(p==NULL)return false;LNode *q=p->next;//q指向p的后繼結點p->data=p->next->data;//和后繼結點交換數據域p->next=q->next;free(q);return true;}

①初始狀態,LNode *q=p->next;
在這里插入圖片描述
②交換數據域,p->data=p->next->data;
在這里插入圖片描述
③改變指針指向,p->next=q->next;,最后再釋放q所指向的空間,free(q);
在這里插入圖片描述
注意:如果要刪除的是最后一個結點的話,q會指向null,這時候只能采用傳入頭指針遍歷,找到前驅結點的辦法來刪除。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/89400.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/89400.shtml
英文地址,請注明出處:http://en.pswp.cn/web/89400.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Nextjs官方文檔異疑惑

第一個區別&#xff1a;不同的頁面對應的路由器設定&#xff01; 繼續用 app 路由器&#xff08;推薦&#xff0c;Next.js 未來主流&#xff09; 路由規則&#xff1a;app 目錄下&#xff0c;文件夾 page.tsx 對應路由。例如&#xff1a; app/page.tsx → 對應 / 路由&#xf…

突破AI模型訪問的“光標牢籠”:長上下文處理與智能環境隔離實戰

> 當AI模型面對浩瀚文檔卻只能處理零星片段,當關鍵信息散落各處而模型“視而不見”,我們該如何打破這堵無形的墻? 在自然語言處理領域,**輸入長度限制**(常被稱為“光標區域限制”)如同一個無形的牢籠,嚴重制約了大型語言模型(LLM)在真實場景中的應用潛力。無論是分…

AI 智能質檢系統在汽車制造企業的應用?

某知名汽車制造企業在其龐大且復雜的生產流程中&#xff0c;正面臨著棘手的汽車零部件質檢難題。傳統的人工質檢方式&#xff0c;完全依賴人工的肉眼觀察與簡單工具測量。質檢員們長時間處于高強度的工作狀態&#xff0c;精神高度集中&#xff0c;即便如此&#xff0c;由于人工…

設計模式》》門面模式 適配器模式 區別

// 復雜子系統 class CPU {start() { console.log("CPU啟動"); } } class Memory {load() { console.log("內存加載"); } } class HardDrive {read() { console.log("硬盤讀取"); } }// 門面 class ComputerFacade {constructor() {this.cpu ne…

windows內核研究(驅動開發 第一個驅動程序和調試環境搭建)

驅動開發 第一個驅動程序 驅動的開發流程 1.編寫代碼 -> 生成.sys文件 -> 部署 -> 啟動 -> 停止 ->卸載 // 編寫我們的第一個驅動程序 #include<ntddk.h>// 卸載函數 VOID DrvUnload(PDRIVER_OBJECT DriverObject) {DbgPrint("我被卸載了\n"…

ABP VNext + 多級緩存架構:本地 + Redis + CDN

ABP VNext 多級緩存架構&#xff1a;本地 Redis CDN &#x1f4da; 目錄ABP VNext 多級緩存架構&#xff1a;本地 Redis CDN一、引言 &#x1f680;二、環境與依賴 &#x1f6e0;?三、架構概覽 &#x1f310;請求全鏈路示意 &#x1f6e3;?四、本地內存緩存層 &#x1…

RGBA圖片格式轉換為RGB格式(解決convert轉換的失真問題)

使用convert轉換的問題 OpenCV 的 cv2.cvtColor(…, cv2.COLOR_BGRA2GRAY) 會直接忽略 Alpha 通道的含義&#xff0c;將它當作第四個顏色通道來處理。 轉換公式如下&#xff1a; gray 0.114*255 0.587*0 0.299*0 ≈ 29也就是說&#xff0c;即使 Alpha 為 0&#xff08;完全透…

Spring AI之Prompt開發

文章目錄1 提示詞工程1_核心策略2_減少模型“幻覺”的技巧2 提示詞攻擊防范1_提示注入&#xff08;Prompt Injection&#xff09;2_越獄攻擊&#xff08;Jailbreaking&#xff09;3 數據泄露攻擊&#xff08;Data Extraction&#xff09;4 模型欺騙&#xff08;Model Manipulat…

Java面試(基礎篇) - 第二篇!

未看第一篇的&#xff0c;這里可以直達 Java面試(基礎篇) - 第一篇 Integer對象可以用判斷嗎&#xff1f;為什么&#xff1f; 回答 不可以&#xff0c;因為 比較的是對象的實例&#xff08;內存地址&#xff09;&#xff0c;Integer是有一個緩存機制的&#xff0c;它會將-1…

【C# in .NET】11. 探秘泛型:類型參數化革命

探秘泛型:類型參數化革命 泛型是 C# 和.NET框架中一項革命性的特性,它實現了 “編寫一次,多處復用” 的抽象能力,同時保持了靜態類型的安全性和高性能。與 C++ 模板等其他語言的泛型機制不同,.NET 泛型在 CLR(公共語言運行時)層面提供原生支持,這使得它兼具靈活性、安…

菜單權限管理

菜單管理系統的整體架構1.Menu 菜單表2.role 角色表3.role_menu 角色菜 單關聯表&#xff08;多對多 &#xff09;要找role_id為3的角色能用哪個菜單:SELECT *FROM sys_menu a LEFT JOIN sys_role_menu b ON a.menu_id b.menu_id WHERE role_id3拆分開就是4.user 用戶表5.user…

SQL FOREIGN KEY:詳解及其在數據庫設計中的應用

SQL FOREIGN KEY:詳解及其在數據庫設計中的應用 引言 在數據庫設計中,數據完整性是至關重要的。SQL FOREIGN KEY(外鍵)是實現數據完整性的一種有效手段。本文將詳細解釋SQL FOREIGN KEY的概念、用途以及在實際數據庫設計中的應用。 外鍵概述 1. 定義 外鍵(FOREIGN KE…

[yotroy.cool] 記一次 spring boot 項目寶塔面板部署踩坑

個人博客https://www.yotroy.cool/&#xff0c;感謝關注&#xff5e; 圖片資源可能顯示不全&#xff0c;請前往博客查看哦&#xff01;部署了個新項目&#xff0c;給我整抑郁了。。。下面是踩坑過程 寶塔面板 MySql5.7 版本 root 密碼錯誤 這個MySQL5.7 安裝完后就跑不了&#…

前端之HTML學習

HTML 學習筆記 前端三大件 HTML&#xff1a;超文本標記語言&#xff08;HyperText Markup Language&#xff09;CSS&#xff1a;層疊樣式表JavaScript&#xff1a;客戶端腳本語言常用框架&#xff1a;jQuery Vue 3(Element plus) HTML 基本概念 超文本&#xff1a;包含圖像…

迅速高效從web2到web3轉型 ,開啟遠程工作

Web2向Web3的轉型&#xff0c;是技術、產品、組織結構和商業模式的深度變革。若要迅速且高效地完成這個轉型&#xff0c;需要清晰的路徑規劃和戰略執行。 目錄 &#x1f501; 一、理解核心區別&#xff1a;Web2 vs Web3 &#x1f680; 二、轉型路徑 1. 選擇合適的切入點 …

區塊鏈開發協作工具全景圖:從智能合約管理到去中心化治理

&#x1f4a5; 三重絞索&#xff1a;區塊鏈開發的至暗時刻 1. 版本管理的深淵 當某DeFi團隊凌晨修復漏洞時&#xff0c;發現生產環境運行的竟是兩周前的廢棄分支——37%的項目因代碼分支混亂引發生產事故&#xff08;Electric Capital 2024&#xff09;。智能合約的版本漂移如同…

冒泡排序、選擇排序、插入排序、快速排序

目錄 1. 冒泡排序 (Bubble Sort) 算法思路分析 代碼實現 復雜度分析 2. 選擇排序 (Selection Sort) 算法思路分析 代碼實現 復雜度分析 3. 插入排序 (Insertion Sort) 算法思路分析 代碼實現 復雜度分析 4. 快速排序 (Quick Sort) 算法思路分析 代碼實現 復雜度…

PHP語言基礎知識(超詳細)第一節

一. PHP簡介: PHP即“超文本預處理器”,創建于1994年,是一種通用開源腳本語言。PHP是在服務器端執行的腳本語言,與C語言類似,是常用的網站編程語言。PHP獨特的語法混合了C、Java、Perl以及 PHP 自創的語法。利于學習,使用廣泛,主要適用于Web開發領域。 二. PHP的優點:…

Reloaded-II項目:解決GitHub下載Mod缺少DLL文件的問題

Reloaded-II項目&#xff1a;解決GitHub下載Mod缺少DLL文件的問題 問題現象分析 在使用Reloaded-II項目加載從GitHub下載的"Debug Stuff"模組時&#xff0c;用戶遇到了一個常見的技術問題&#xff1a;系統提示缺少DLL文件&#xff0c;導致模組無法正常運行。這種情況…

0-1搭建springboot+vue的教務管理系統(核心源碼)

目錄 后端核心代碼&#xff1a; control層 service 層 mapper層 后端核心代碼&#xff1a; control層&#xff1a; classControlsImpl package com.itheima.controls.impl;import com.itheima.mapper.ClassMapper; import com.itheima.pojo.Clazz; import com.itheima.po…