【數據結構】單鏈表的使用

單鏈表的使用

    • 1、基本概念
    • 2、鏈表的分類
    • 3、鏈表的基本操作
      • a、單鏈表節點設計
      • b、單鏈表初始化
      • c、單鏈表增刪節點
        • **節點頭插:**
        • **節點尾插:**
        • **新節點插入指定節點后:**
        • 節點刪除:
      • d、單鏈表修改節點
      • e、單鏈表遍歷,并打印數據
    • 4、鏈表優缺點
    • 5、完整示例代碼

1、基本概念

  • 順序表:順序存儲的線性表。
  • 鏈式表:鏈式存儲的線性表,簡稱鏈表。
    既然順序存儲中的數據因為擠在一起而導致需要成片移動,那很容易想到的解決方案是將數據離散地存儲在不同內存塊中,然后在用來指針將它們串起來。這種樸素的思路所形成的鏈式線性表,就是所謂的鏈表。

順序表和鏈表在內存在的基本樣態如下圖所示:

  • 順序表:

在這里插入圖片描述
鏈表:
在這里插入圖片描述

2、鏈表的分類

\quad 根據鏈表中各個節點之間使用指針的個數,以及首尾節點是否相連,可以將鏈表細分為如下種類:
1.單向鏈表
2.單向循環鏈表
3.雙向循環鏈表
\quad 這些不同鏈表的操作都是差不多的,只是指針數目的異同。以最簡單的單向鏈表為例,其基本示意圖如下所示:
在這里插入圖片描述上圖中,所有的節點均保存一個指針,指向其邏輯上相鄰的下一個節點(末尾節點指向空)。
另外注意到,整條鏈表用一個所謂的頭指針 head 來指向,由 head 開始可以找到鏈表中的任意一個節點。head 通常被稱為頭指針

3、鏈表的基本操作

  1. 節點設計
  2. 初始化空鏈表
  3. 增刪節點
  4. 鏈表遍歷(改查)
  5. 銷毀鏈表

下面著重針對這幾項常見操作,講解單向鏈表的處理。

a、單鏈表節點設計

單向鏈表的節點非常簡單,節點中除了要保存用戶數據之外(這里以整型數據為例),只需要增加一個指向本類節點的指針即可,如下所示:

typedef struct single_list{// 數據域--》真實的數據int data;    				// 以整型數據為例// 指針域struct single_list *next; 	// //用來指向下一個元素在內存中的首地址
}single_list_t;

b、單鏈表初始化

\quad 首先,空鏈表有兩種常見的形式。一種是帶頭結點的,一種是不帶頭結點的。所謂的頭結點是不存放有效數據的節點,僅僅用來方便操作,如下:
在這里插入圖片描述
而不帶頭結點的空鏈表如下所示:
在這里插入圖片描述
\quad 由于頭結點是不存放有效數據的,因此如果空鏈表中帶有頭結點,那么頭指針 head 將永遠不變,這會給以后的鏈表操作帶來些許便捷。
下面以帶頭結點的鏈表為例,展示單向鏈表的初始化的示例代碼:

single_list_t *single_list_init()
{single_list_t *head_node = malloc(sizeof(single_list_t));if (head_node != NULL){head_node->next = NULL;}return head_node;
}

c、單鏈表增刪節點

\quad 相對于順序表需要整片移動數據,鏈表增刪節點只需要修改幾個相關指針的指向,動作非常快速。
\quad 與順序表類似,可以對一條鏈表中的任意節點進行增刪操作,示例代碼:

節點頭插:
int insert_list_head(int newdata, single_list_t *list)
{// 申請一個節點 -堆空間single_list_t *new_node = malloc(sizeof(single_list_t));// 初始化數據域new_node->data = newdata;new_node->next = NULL;// 插入節點new_node->next = list->next;list->next = new_node;return 0;
}
節點尾插:
int insert_list(int newdata, single_list_t *list)
{// 申請一個節點 -堆空間single_list_t *new_node = malloc(sizeof(single_list_t));// 初始化數據域new_node->data = newdata;new_node->next = NULL;// 定義指針p去找到鏈表的尾部single_list_t *p = list;while (p->next != NULL){p = p->next;}// 此時p已經到最后一個節點的位置p->next = new_node;return 0;
}
新節點插入指定節點后:
int insert_list_mid(int olddata, int newdata, single_list_t *list)
{// 找到要插入的節點single_list_t *p = list;while (p->next != NULL){p = p->next;if (p->data == olddata) // 待插入的節點在鏈表中間{break;}}// 申請一個新的節點 single_list_t *new_node = malloc(sizeof(single_list_t));// 初始化數據域new_node->data = newdata;new_node->next = NULL;// p指向最后一個節點if (p->next == NULL){// 最后一個節點是要插入的節點if (p->data == olddata){new_node->next = p->next; // 先讓新增加的節點指向找到節點的下一個節點p->next = new_node;   // 再將該節點指向新增加的節點}else{printf("要插入的數據不存在\n");return -1;}}else // 遍歷到中間找到需要插入的節點{new_node->next = p->next; // 先讓新增加的節點指向找到節點的下一個節點p->next = new_node;   // 再將該節點指向新增加的節點}return 0;
}
節點刪除:
int list_delnode(int deldata, single_list_t *list)
{single_list_t *q = list;single_list_t *p = list->next;while (p->next != NULL){// 找到要刪除的節點并進行刪除if (p->data == deldata){q->next = p->next;  // 將q指向的節點指向被刪除節點的下一個節點p->next = NULL;     // p節點的next指針指向NULLfree(p);    // 釋放p后此時p是野指針p = q->next;// 將p指向被刪除節點的下一個節點}else{p = p->next;q = q->next;}  }// 遍歷到最后一個節點if (p->next == NULL){// 若最后一個節點是要刪除的節點,則刪除if (p->data == deldata){q->next = p->next;p->next = NULL;free(p);}else{printf("最后一個節點不是要刪除的節點\n");return 0;}}
}

d、單鏈表修改節點

int list_update_node(int old_data, int new_data, single_list_t *list)
{single_list_t *p = list;while (p->next != NULL){p = p->next;  // p指向下一個節點if (p->data == old_data){p->data = new_data;}}return 0;
}

e、單鏈表遍歷,并打印數據

int list_show(single_list_t *list)
{single_list_t *p = list;while (p->next != NULL){p = p->next;printf("當前p指向的節點數據:%d\n", p->data);}
}

4、鏈表優缺點

\quad 鏈式存儲中,所有節點的存儲位置是隨機的,他們之間的邏輯關系用指針來確定,跟物理存儲位置無關,因此從上述示例代碼可以很清楚看到,增刪數據都非常迅速,不需要移動任何數據。另外,又由于位置與邏輯關系無關,因此也無法直接訪問某一個指定的節點,只能從頭到尾按遍歷的方式一個個找到想要的節點。簡單講,鏈式存儲的優缺點跟順序存儲幾乎是相對的。
總結其特點如下:

  • 優點
    a.插入、刪除時只需要調整幾個指針,無需移動任何數據
    b.當數據節點數量較多時,無需一整片較大的連續內存空間,可以靈活利用離散的內存
    c.當數據節點數量變化劇烈時,內存的釋放和分配靈活,速度快
  • 缺點
    a.在節點中,需要多余的指針來記錄節點之間的關聯
    b.所有數據都是隨機存儲的,不支持立即訪問任意一個隨機數據。

5、完整示例代碼

#include <stdio.h>
#include <stdlib.h>// 1.封裝一個結構體來表示單鏈表
typedef struct single_list{int data;struct single_list *next;
}single_list_t;// 2.初始化單鏈表-->定義結構體變量 創建頭節點
single_list_t *single_list_init()
{single_list_t *head_node = malloc(sizeof(single_list_t));if (head_node != NULL){head_node->next = NULL;}return head_node;
}// 頭插
int insert_list_head(int newdata, single_list_t *list)
{// 申請一個節點 -堆空間single_list_t *new_node = malloc(sizeof(single_list_t));// 初始化數據域new_node->data = newdata;new_node->next = NULL;// 插入節點new_node->next = list->next;list->next = new_node;return 0;
}
/*@brief:3.插入數據-->尾插(在最后一個有效成員的后面插入數據)*@param(in):  newdata :待插入的數據  list:待插入的鏈表*@param(out):  *@retval:    
*/
int insert_list(int newdata, single_list_t *list)
{// 申請一個節點 -堆空間single_list_t *new_node = malloc(sizeof(single_list_t));// 初始化數據域new_node->data = newdata;new_node->next = NULL;// 定義指針p去找到鏈表的尾部single_list_t *p = list;while (p->next != NULL){p = p->next;}// 此時p已經到最后一個節點的位置p->next = new_node;return 0;
}// 中間插入
int insert_list_mid(int olddata, int newdata, single_list_t *list)
{// 找到要插入的節點single_list_t *p = list;while (p->next != NULL){p = p->next;if (p->data == olddata){break;}}// 申請一個節點 -堆空間single_list_t *new_node = malloc(sizeof(single_list_t));// 初始化數據域new_node->data = newdata;new_node->next = NULL;// p指向最后一個節點if (p->next == NULL){if (p->data == olddata){new_node->next = p->next; // 先讓新增加的節點指向找到節點的下一個節點p->next = new_node;   // 再將該節點指向新增加的節點}else{printf("要插入的數據不存在\n");return -1;}}else // 遍歷到中間找到需要插入的節點{new_node->next = p->next; // 先讓新增加的節點指向找到節點的下一個節點p->next = new_node;   // 再將該節點指向新增加的節點}return 0;
}
// 刪除節點
int list_delnode(int deldata, single_list_t *list)
{single_list_t *q = list;single_list_t *p = list->next;while (p->next != NULL){// 找到要刪除的節點并進行刪除if (p->data == deldata){q->next = p->next;  // 將q指向的節點指向被刪除節點的下一個節點p->next = NULL;     // p節點的next指針指向NULLfree(p);    // 釋放p后此時p是野指針p = q->next;// 將p指向被刪除節點的下一個節點}else{p = p->next;q = q->next;}  }// 遍歷到最后一個節點if (p->next == NULL){// 若最后一個節點是要刪除的節點,則刪除if (p->data == deldata){q->next = p->next;p->next = NULL;free(p);}else{printf("最后一個節點不是要刪除的節點\n");return 0;}}
}
// 修改節點
int list_update_node(int old_data, int new_data, single_list_t *list)
{single_list_t *p = list;while (p->next != NULL){p = p->next;  // p往后移動if (p->data == old_data){p->data = new_data;}}return 0;
}// 4.遍歷鏈表,打印節點數據
int list_show(single_list_t *list)
{single_list_t *p = list;while (p->next != NULL){p = p->next;printf("當前p指向的節點數據:%d\n", p->data);}
}int main(int argc, char const *argv[])
{// 初始化單鏈表single_list_t *my_list = single_list_init();// 往鏈表插入數據insert_list(15, my_list);insert_list(18, my_list);insert_list(15, my_list);insert_list(25, my_list);insert_list(666, my_list);insert_list(123, my_list);insert_list(11111111, my_list);insert_list_mid(666, 777, my_list);insert_list_mid(1, 222, my_list);insert_list_head(15, my_list);printf("============插入的節點============\n");list_show(my_list);printf("============插入的節點============\n");// 刪除節點list_delnode(25,my_list);printf("============刪除后的節點============\n");list_show(my_list); // 打印數據printf("============刪除后的節點============\n");// 修改數據list_update_node(123, 234, my_list);printf("============修改后的節點============\n");list_show(my_list); // 打印數據printf("============修改后的節點============\n");return 0;
}
/*
執行結果:
要插入的數據不存在
============插入的節點============
當前p指向的節點數據:15
當前p指向的節點數據:15
當前p指向的節點數據:18
當前p指向的節點數據:15
當前p指向的節點數據:25
當前p指向的節點數據:666
當前p指向的節點數據:777
當前p指向的節點數據:123
當前p指向的節點數據:11111111
============插入的節點============
最后一個節點不是要刪除的節點
============刪除后的節點============
當前p指向的節點數據:15
當前p指向的節點數據:15
當前p指向的節點數據:18
當前p指向的節點數據:15
當前p指向的節點數據:666
當前p指向的節點數據:777
當前p指向的節點數據:123
當前p指向的節點數據:11111111
============刪除后的節點============
============修改后的節點============
當前p指向的節點數據:15
當前p指向的節點數據:15
當前p指向的節點數據:18
當前p指向的節點數據:15
當前p指向的節點數據:666
當前p指向的節點數據:777
當前p指向的節點數據:234
當前p指向的節點數據:11111111
============修改后的節點============
*/

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

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

相關文章

虛幻引擎是什么?

Unreal Engine&#xff0c;是一款由Epic Games開發的游戲引擎。該引擎主要是為了開發第一人稱射擊游戲而設計&#xff0c;但現在已經被成功地應用于開發模擬游戲、恐怖游戲、角色扮演游戲等多種不同類型的游戲。虛幻引擎除了被用于開發游戲&#xff0c;現在也用于電影的虛擬制片…

Linux(Centos 7.6)yum源配置

yum是rpm包的管理工具&#xff0c;可以自動安裝、升級、刪除軟件包的功能&#xff0c;可以自動解決軟件包之間的依賴關系&#xff0c;使得用戶更方便軟件包的管理。要使用yum必須要進行配置&#xff0c;個人將其分為三類&#xff0c;本地yum源、局域網yum源、第三方yum源&#…

Linux上更新jar包里的某個class文件

目標&#xff1a;替換voice-1.0.jar里的TrackHandler.class文件 一.查詢jar包里TrackHandler.class所在的路徑 jar -tvf voice-1.0.jar |grep TrackHandler 二.解壓出TrackHandler.class文件 jar -xvf voice-1.0.jar BOOT-INF/classes/com/yf/rj/handler/TrackHandler.cla…

機器學習中回歸預測模型中常用四個評價指標MBE、MAE、RMSE、R2解釋

在機器學習中&#xff0c;評估模型性能時常用的四個指標包括平均絕對誤差&#xff08;Mean Absolute Error, MAE&#xff09;、均方誤差&#xff08;Mean Squared Error, MSE&#xff09;、均方根誤差&#xff08;Root Mean Squared Error, RMSE&#xff09;和決定系數&#xf…

基于SpringBoot的Jwt認證以及密碼aes加密解密技術

目錄 前言 1.SpringBoot項目的創建 2.相關技術 3.項目架構 4.項目關鍵代碼 5.項目最終的運行效果 ?編輯 6.PostMan測試接口結果 前言 學習了SpringBoot之后&#xff0c;才覺得SpringBoot真的很方便&#xff0c;相比傳統的SSH&#xff0c;SSM&#xff0c;SpringBo…

uniapp下載打開實現方案,支持安卓ios和h5,下載文件到指定目錄,安卓文件管理內可查看到

uniapp下載&打開實現方案&#xff0c;支持安卓ios和h5 Android&#xff1a; 1、申請本地存儲讀寫權限 2、創建文件夾&#xff08;文件夾不存在即創建&#xff09; 3、下載文件 ios&#xff1a; 1、下載文件 2、保存到本地&#xff0c;需要打開文件點擊儲存 使用方法&…

77、將adaface的mtcnn模型npy文件轉成atlas310p模型,并進行推理

基本思想:將adaface的mtcnn模型npy文件轉成atlas310p模型進行推理。同時比對結果 ubuntu@ubuntu:~$ git clone https://github.com/mk-minchul/AdaFace.git Cloning into AdaFace... remote: Enumerating objects: 236, done. remote: Counting objects: 100% (109/109), don…

Spark SQL DML語句

【圖書介紹】《Spark SQL大數據分析快速上手》-CSDN博客 《Spark SQL大數據分析快速上手》【摘要 書評 試讀】- 京東圖書 Spark本地模式安裝_spark3.2.2本地模式安裝-CSDN博客 DML&#xff08;Data Manipulation Language&#xff0c;數據操作語言&#xff09;操作主要用來對…

農歷節日倒計時:基于Python的公歷與農歷日期轉換及節日查詢小程序

農歷節日倒計時&#xff1a;基于Python的公歷與農歷日期轉換及節日查詢小程序 摘要 又是一年春節即將到來&#xff0c;突然想基于Python編寫一個農歷節日的倒計時小程序。該程序能夠根據用戶輸入的農歷節日名稱&#xff0c;計算出距離該節日還有多少天。通過使用lunardate庫進…

線性直流電流

電阻網絡的等效 等效是指被化簡的電阻網絡與等效電阻具有相同的 u-i 關系 (即端口方程)&#xff0c;從而用等效電阻代替電阻網絡之后&#xff0c;不 改變其余部分的電壓和電流。 串聯等效&#xff1a; 并聯等效&#xff1a; 星角變換 若這兩個三端網絡是等效的&#xff0c;從任…

CDN(Content Delivery Network,內容分發網絡)

CDN&#xff08;Content Delivery Network&#xff0c;內容分發網絡&#xff09;是一種通過在網絡中部署分布式的服務器集群&#xff0c;將網站內容分發到最接近用戶的服務器節點&#xff0c;以提高用戶訪問速度和穩定性的重要網絡基礎設施。CDN的核心思想是讓用戶就近獲取所需…

B站推薦模型數據流的一致性架構

01 背景 推薦系統的模型&#xff0c;通過學習用戶歷史行為來達到個性化精準推薦的目的&#xff0c;因此模型訓練依賴的樣本數據&#xff0c;需要包括用戶特征、服務端推薦的視頻特征&#xff0c;以及用戶在推薦視頻上是否有一系列的消費行為。 推薦模型數據流&#xff0c;即為…

【LeetCode】839、相似字符串組

【LeetCode】839、相似字符串組 文章目錄 一、并查集1.1 并查集 二、多語言解法 一、并查集 1.1 并查集 求共有幾組, 聯想到并查集, 即并查集有幾個集合 字符串相似: 相差0個字符, 或2個字符 其中所有字符串長度都相同, 是比較方便處理的 // go var sets int var father […

你不需要對其他成年人的情緒負責

在這個紛繁復雜的世界里&#xff0c;每個人都是獨一無二的個體&#xff0c;背負著各自的故事、夢想與煩惱。在人際交往的廣闊舞臺上&#xff0c;我們時常會遇到這樣的情境&#xff1a;朋友、同事、家人&#xff0c;甚至是陌生人&#xff0c;他們的情緒似乎總能不經意間影響到我…

官宣!低空經濟司,掛牌成立!

近日&#xff0c;國家發展改革委網站“機關司局”欄目悄然更新&#xff0c;一個新設立的部門——低空經濟發展司&#xff08;簡稱“低空司”&#xff09;正式進入公眾視野。低空司的成立&#xff0c;無疑是對當前國家經濟發展形勢的深刻把握和前瞻布局。 低空經濟是以各類低空飛…

接口調用限頻(代理模式+滑動窗口)

目錄 代碼示例 接口 代理 接口實現 限流工廠 限流處理器接口 直接交換處理器 限流處理器 限流配置 滑動窗口限流 通過代理模式滑動窗口&#xff0c;限流請求第三方平臺&#xff0c;避免出現第三方平臺拋出限流異常&#xff0c;影響正常業務流程&#xff0c;從出口出發…

不安全物聯網的輕量級加密:綜述

Abstract 本文綜述了針對物聯網&#xff08;IoT&#xff09;的輕量級加密解決方案。這項綜述全面覆蓋了從輕量級加密方案到不同類型分組密碼的比較等多個方面。同時&#xff0c;還對硬件與軟件解決方案之間的比較進行了討論&#xff0c;并分析了當前最受信賴且研究最深入的分組…

【小程序】全局數據共享

目錄 全局數據共享 1. 什么是全局數據共享 2. 小程序中的全局數據共享方案 全局數據共享 - MobX 1. 安裝 MobX 相關的包 2. 創建 MobX 的 Store 實例 3. 將 Store 中的成員綁定到頁面中 4. 在頁面上使用 Store 中的成員 ?5. 將 Store 中的成員綁定到組件中 6. 在組件中…

自動化測試- 自動化測試模型

目錄 自動化測試模型簡介 1、線性模型 舉例 測試頁面html文件 測試腳本 2. 關鍵字驅動測試&#xff08;Keyword-Driven Testing&#xff09; 需測試內容 關鍵字驅動測試框架 創建測試用例文件 運行測試 3. 數據驅動測試&#xff08;Data-Driven Testing&#xff09; …

【GlobalMapper精品教程】091:根據指定字段融合圖斑(字段值相同融合到一起)

文章目錄 一、加載數據二、符號化三、融合圖斑1. 根據圖斑位置進行融合2. 根據指定字段四、注意事項一、加載數據 訂閱專欄后,從私信中查收配套實驗數據包,找到data091.rar,解壓并加載,如下圖所示: 屬性表如下: 二、符號化 為了便于比對不同的融合結果,查看屬性表根據…