Java數據結構——線性表Ⅱ

一、鏈式存儲結構概述

1. 基本概念(邏輯分析)

核心思想:用指針將離散的存儲單元串聯成邏輯上連續的線性表

設計動機:解決順序表 "預先分配空間" 與 "動態擴展" 的矛盾

關鍵特性

  1. 結點空間動態分配,適應數據量動態變化
  2. 插入刪除僅需修改指針,無需移動大量元素
  3. 存儲單元離散,不要求連續內存空間

二、單鏈表(Single Linked List)

1. 結點與鏈表類定義(設計思路)

(1)LinkNode 結點類設計
  • 數據域 data:存儲元素值,采用泛型 E 實現類型通用化
  • 指針域 next:指向下一結點,形成單向鏈表鏈
  • 構造方法重載:提供無參(初始空結點)和有參(初始化數據)兩種構造方式
(2)LinkListClass 鏈表類設計
  • 頭結點 head:啞結點設計,避免處理空表時的特殊情況
  • 空表初始化:頭結點的 next 指針置 null,形成 "頭結點 + 空數據區" 的初始結構
 
// 單鏈表結點泛型類(邏輯:每個結點保存數據和后繼指針)class LinkNode<E> {E data; // 數據域,存儲元素值LinkNode<E> next; // 指針域,指向下一結點public LinkNode() {next = null; // 無參構造:初始時不指向任何結點}public LinkNode(E d) {data = d; // 有參構造:初始化數據域next = null;}}// 單鏈表泛型類(邏輯:通過頭結點管理整個鏈表)public class LinkListClass<E> {LinkNode<E> head; // 頭結點,不存儲實際數據public LinkListClass() {head = new LinkNode<E>(); // 創建頭結點head.next = null; // 初始時頭結點不指向任何數據結點}// 基本運算算法...}

2. 核心操作實現(邏輯解析)

(1)插入操作(在 p 結點后插入 s 結點)
  • 核心難點:如何在不丟失原指針的前提下完成插入
  • 操作步驟
  1. 先讓新結點 s 指向 p 的原后繼(避免指針丟失)
  2. 再讓 p 指向新結點 s(完成鏈表連接)
  • 安全原則:始終遵循 "先連接新結點后繼,再連接原結點后繼" 的順序
 
// 插入邏輯示意圖(思路:兩步指針修改完成插入)s.next = p.next; // 步驟1:新結點先指向原后繼,防止指針丟失p.next = s; // 步驟2:原結點指向新結點,完成插入
(2)刪除操作(刪除 p 結點的后繼)
  • 核心思路:通過修改 p 的 next 指針,直接跳過待刪除結點
  • 內存管理:Java 自動垃圾回收,無需手動釋放結點內存
 
p.next = p.next.next; // 思路:讓p直接指向原后繼的后繼,跳過待刪除結點
(3)頭插法建表(CreateListF)
  • 算法思想
  1. 從空表開始,逐個處理數組元素
  2. 每個新結點始終插入到表頭(頭結點之后)
  3. 最終鏈表順序與數組順序相反
  • 適用場景:需要逆序構建鏈表的場景
public void CreateListF(E[] a) {LinkNode<E> s;for (int i = 0; i < a.length; i++) {s = new LinkNode<E>(a[i]);s.next = head.next; // 新結點先指向原表頭,保持鏈表連續性head.next = s; // 頭結點指向新結點,完成表頭插入}}
(4)尾插法建表(CreateListR)
  • 算法思想
  1. 用尾指針 t 跟蹤鏈表尾部
  2. 新結點始終插入到 t 之后
  3. 每次插入后更新 t 為新的尾結點
  • 關鍵優化:避免頭插法的 O (n) 查找尾結點操作,時間復雜度優化為 O (1)
public void CreateListR(E[] a) {LinkNode<E> s, t;t = head; // t初始指向頭結點,作為初始尾結點for (int i = 0; i < a.length; i++) {s = new LinkNode<E>(a[i]);t.next = s; // 尾結點指向新結點t = s; // 尾指針更新為新結點}t.next = null; // 最后一個結點的next置null,標識鏈表尾部}

3. 基本運算實現(邏輯拆解)

(1)獲取指定序號的結點(geti)
  • 算法思路
  1. 從 head 開始遍歷
  2. 用計數器 j 記錄當前遍歷到的序號
  3. 當 j 等于目標序號 i 時返回對應結點
  • 邊界處理:i=-1 時返回頭結點(用于插入操作的前驅查找)
private LinkNode<E> geti(int i) {LinkNode<E> p = head; // 從頭結點開始遍歷int j = -1; // j=-1對應頭結點,j=0對應首數據結點while (j < i) {j++;p = p.next; // 指針后移}return p; // 返回序號為i的結點}
(2)添加元素到表尾(Add)
  • 算法步驟
  1. 新建結點 s 存儲元素 e
  2. 查找當前尾結點(p.next==null)
  3. 將尾結點的 next 指向 s
  • 時間復雜度:O (n),需遍歷鏈表查找尾結點
public void Add(E e) {LinkNode<E> s = new LinkNode<E>(e);LinkNode<E> p = head;while (p.next != null) {p = p.next; // 循環找到尾結點}p.next = s; // 尾結點指向新結點}
(3)求表長度(size)
  • 計數思路
  1. 從 head 開始遍歷
  2. 每次遇到非空 next 時計數器 + 1
  3. 直到遇到 null 指針(鏈表尾部)
  • 優化方向:若維護 size 變量,可將時間復雜度降為 O (1)
public int size() {LinkNode<E> p = head;int cnt = 0;while (p.next != null) {cnt++;p = p.next; // 指針后移并計數}return cnt;}

4. 應用算法示例(問題解決思路)

(1)查找中間位置元素(兩種算法對比)

計數法(Middle1)

  • 問題分析:已知鏈表長度 n,中間位置為:
  • 奇數長度:(n-1)/2+1(如 n=3,位置 2
  • 偶數長度:(n-1)/2+1(如 n=4,位置 2)
  • 本質:通過數學計算減少遍歷次數
  • 算法步驟
  1. 計算長度 n
  2. 遍歷 (n-1)/2 次到達中間結點
public static int Middle1(LinkListClass<Integer> L) {int j = 1, n = L.size();LinkNode<Integer> p = L.head.next; // p指向首結點(序號1)while (j <= (n - 1) / 2) { // 需遍歷(n-1)/2次j++;p = p.next;}return p.data;}

快慢指針法(Middle2)

  • 核心思想
  • 快指針每次走 2 步,慢指針每次走 1 步
  • 當快指針到達末尾時,慢指針恰好到達中間
  • 時間優化:只需 O (n) 時間,無需兩次遍歷
public static int Middle2(LinkListClass<Integer> L) {LinkNode<Integer> slow = L.head.next; // 慢指針LinkNode<Integer> fast = L.head.next; // 快指針while (fast.next != null && fast.next.next != null) {slow = slow.next; // 慢指針走1步fast = fast.next.next; // 快指針走2步}return slow.data; // 快指針無法再走2步時,慢指針指向中間}
(2)逆置鏈表(Reverse)
  • 算法思路
  1. 將原鏈表置為空表(head.next=null)
  2. 逐個取出原鏈表結點
  3. 每次將結點插入到新鏈表的表頭
  • 關鍵技巧:使用臨時變量 q 保存后繼結點,防止指針丟失
public static void Reverse(LinkListClass<Integer> L) {LinkNode<Integer> p = L.head.next, q; // p指向首結點L.head.next = null; // 清空原鏈表(僅保留頭結點)while (p != null) {q = p.next; // 保存p的后繼結點,防止斷鏈p.next = L.head.next; // 插入到表頭(頭結點之后)L.head.next = p;p = q; // p指向下一個待處理結點}}

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

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

    相關文章

    技術基石:SpreadJS 引擎賦能極致體驗

    在能源行業數字化轉型的浪潮中&#xff0c;青島國瑞信息技術有限公司始終以技術創新為核心驅動力&#xff0c;不斷探索前沿技術在能源領域的深度應用。其推出的 RCV 行列視生產數據應用系統之所以能夠在行業內脫穎而出&#xff0c;離不開背后強大的技術基石 ——SpreadJS 引擎。…

    Typora - Typora 打字機模式

    Typora 打字機模式 1、基本介紹 Typora 打字機模式&#xff08;Typewriter Mode&#xff09;是一種專注于當前寫作行的功能 打字機模式會自動將正在編輯的行保持在屏幕中央&#xff0c;讓用戶更集中注意力&#xff0c;類似于傳統打字機的體驗 2、開啟方式 點擊 【視圖】 -…

    3.0 compose學習:MVVM框架+Hilt注解調用登錄接口

    文章目錄 前言&#xff1a;1、添加依賴1.1 在settings.gradle.kts中添加1.2 在應用級的build.gradle.kts添加插件依賴1.3 在module級的build.gradle.kts添加依賴 2、實體類2.1 request2.2 reponse 3、網絡請求3.1 ApiService3.2 NetworkModule3.3 攔截器 添加token3.4 Hilt 的 …

    git學習資源

    動畫演示&#xff1a;Learn Git Branching 終極目標&#xff08;能看懂即入門&#xff09;&#xff1a;git 簡明指南 Git 教程 | 菜鳥教程

    C++ 第二階段:模板編程 - 第一節:函數模板與類模板

    目錄 一、模板編程的核心概念 1.1 什么是模板編程&#xff1f; 二、函數模板詳解 2.1 函數模板的定義與使用 2.1.1 基本語法 2.1.2 示例&#xff1a;通用交換函數 2.1.3 類型推導規則 2.2 函數模板的注意事項 2.2.1 普通函數與函數模板的調用規則 2.2.2 隱式類型轉換…

    Docker 報錯“x509: certificate signed by unknown authority”的排查與解決實錄

    目錄 &#x1f527;Docker 報錯“x509: certificate signed by unknown authority”的排查與解決實錄 &#x1f4cc; 問題背景 &#x1f9ea; 排查過程 步驟 1&#xff1a;確認加速器地址是否可訪問 步驟 2&#xff1a;檢查 Docker 是否真的使用了鏡像加速器 步驟 3&…

    達夢以及其他圖形化安裝沒反應或者報錯No more handles [gtk_init_check() failed]

    本人安裝問題和解決步驟如下&#xff0c;僅供參考 執行 DMInstall.bin 報錯 按照網上大部分解決方案 export DISPLAY:0.0 xhost 重新執行 DMInstall.bin&#xff0c;無報錯也無反應 安裝xclock測試也是同樣效果&#xff0c;無報錯也無反應 最開始猜測可能是連接工具問題&a…

    項目節奏不一致時,如何保持全局平衡

    項目節奏不一致時&#xff0c;如何保持全局平衡的關鍵在于&#xff1a;構建跨項目協調機制、合理配置資源、建立共享節奏看板、優先明確戰略驅動、引入緩沖與預警機制。其中&#xff0c;構建跨項目協調機制尤為關鍵&#xff0c;它能將各項目的排期、優先級和風險實時聯動&#…

    macOS - 安裝微軟雅黑字體

    文章目錄 1、下載資源2、安裝3、查看字體 app4、卸載字體 macOS 中打開 Windows 傳輸過來的文件的時候&#xff0c;經常會提示 xxx 字體缺失。下面以安裝 微軟雅黑字體為例。 1、下載資源 https://github.com/BronyaCat/Win-Fonts-For-Mac 2、安裝 雙擊 Fonts 文件夾下的 msy…

    ArkUI-X資源分類與訪問

    應用開發過程中&#xff0c;經常需要用到顏色、字體、間距、圖片等資源&#xff0c;在不同的設備或配置中&#xff0c;這些資源的值可能不同。 應用資源&#xff1a;借助資源文件能力&#xff0c;開發者在應用中自定義資源&#xff0c;自行管理這些資源在不同的設備或配置中的…

    11-StarRocks故障診斷FAQ

    StarRocks故障診斷FAQ 概述 本文檔整理了StarRocks故障診斷過程中常見的問題和解決方案,涵蓋了故障排查、日志分析、性能診斷、問題定位等各個方面,幫助用戶快速定位和解決StarRocks相關問題。 故障排查FAQ Q1: 如何排查連接故障? A: 連接故障排查方法: 1. 網絡連通性…

    敏捷項目管理怎么做?4大主流方法論對比及工具適配方案

    在傳統瀑布式項目管理中&#xff0c;需求定義、設計、開發、測試等環節如同工業流水線般嚴格線性推進&#xff0c;展現出強大的流程控制能力。不過今天的軟件迭代周期已壓縮至周級乃至日級&#xff0c;瀑布式管理難以應對需求的快速變化&#xff0c;敏捷式項目管理則以“小步快…

    解決YOLO模型從Python遷移到C++時目標漏檢問題——跨語言部署中的關鍵陷阱與解決方案

    問題背景 當我們將Python訓練的YOLO模型部署到C環境時&#xff0c;常遇到部分目標漏檢問題。這通常源于預處理/后處理差異、數據類型隱式轉換或模型轉換誤差。本文通過完整案例解析核心問題并提供可落地的解決方案。 一、常見原因分析 預處理不一致 Python常用OpenCV&#xff…

    【2025CCF中國開源大會】開放注冊與會議通知(第二輪)

    點擊藍字 關注我們 CCF Opensource Development Committee 2025 CCF中國開源大會 由中國計算機學會主辦的 2025 CCF中國開源大會&#xff08;CCF ChinaOSC&#xff09;擬于 2025年8月2日-3日 在上海召開。本屆大會以“蓄勢引領、眾行致遠”為主題&#xff0c;由上海交通大學校長…

    本地聊天室

    測試版還沒測試過&#xff0c;后面更新不會繼續開源&#xff0c;有問題自行修復 開發環境: PHP版本7.2 Swoole擴展 本地服務器環境&#xff08;如XAMPP、MAMP&#xff09; 功能說明: 注冊/登錄系統&#xff0c;支持本地用戶數據存儲 ? 發送文本、圖片和語音消息 ? 實…

    golang學習隨便記x-調試與雜類(待續)

    編譯與調試 調試時從終端鍵盤輸入 調試帶有需要用戶鍵盤輸入的程序時&#xff0c;VSCode報錯&#xff1a;Unable to process evaluate: debuggee is running&#xff0c;因為調試器不知道具體是哪個終端輸入。需要配置啟動文件 .vscode/launch.json 類似如下&#xff08;注意…

    MultipartFile、File 和 Mat

    1. MultipartFile (來自 Spring Web) 用途&#xff1a; 代表通過 multipart 形式提交&#xff08;通常是 HTTP POST 請求&#xff09;接收到的文件。 它是 Spring Web 中用于處理 Web 客戶端文件上傳的核心接口。 關鍵特性&#xff1a; 抽象&#xff1a; 這是一個接口&#xf…

    .NET 9.0 SignalR 支持修剪和原生 AOT

    什么是 SignalR&#xff1f; SignalR 是一個庫&#xff0c;可用于向應用程序添加實時 Web 功能。它提供了一個簡單的 API&#xff0c;用于創建可從服務器和客戶端調用的服務器到客戶端遠程過程調用 (RPC)。現在&#xff0c;SignalR 在 .NET 8.0 和 .NET 9.0 中支持修剪和原生 …

    下載資源管理

    本文章僅用于作者管理自己的站內資源&#xff0c;方便日后查找&#xff0c;后續更新資源該文章持續更新。 1、環境安裝 python3.11.11環境 python3.7.9 ARM.CMSIS.5.6.0(這個在站內重復上傳了) Nordic8.32.1 java8 2、工具類軟件安裝包 2.1、藍牙類 SI Connect 藍牙OT…

    ??FFmpeg命令全解析:三步完成視頻合并、精準裁剪??、英偉達顯卡加速

    一、裁剪 常規裁剪 根據時長裁剪&#xff0c;常規的裁剪 -c copy 表示直接復制流&#xff08;不重新編碼&#xff09;&#xff0c;速度極快&#xff0c;但要求切割時間必須是關鍵幀。否則裁剪下來的畫面開頭/結尾 會模糊花屏 ffmpeg -i input.mp4 -ss 00:00:30 -to 00:01:00 …