C語言_數據結構總結4:不帶頭結點的單鏈表

純C語言代碼,不涉及C++

0. 結點結構

typedef int ElemType;
typedef struct LNode {
?? ?ElemType data; ?//數據域
?? ?struct LNode* next; ?//指針域
}LNode, * LinkList;

1. 初始化

不帶頭結點的初始化,即只需將頭指針初始化為NULL即可

void InitLink2(LinkList* L) {*L = NULL;
}

2. 頭插法

對于不帶頭結點的單鏈表,頭插法的核心思想是:
每次插入新節點時,將新節點的?next?指針指向當前鏈表的頭節點,然后更新鏈表的頭指針,使其指向新節點。
這樣新節點就成為了鏈表的第一個節點,插入操作的時間復雜度為?O(1)。

int headInsert(LinkList* L, ElemType value) {LinkList s = (LinkList)malloc(sizeof(LNode));if (s == NULL){printf("內存分配失敗!\n");return -2;}s->data = value;s->next = *L;*L = s;  //更新頭結點指向新結點return 0;  //插入成功
}

3. 尾插法

尾插法的核心思路是每次都將新節點插入到鏈表的末尾。
對于不帶頭結點的單鏈表,需要考慮鏈表為空的特殊情況。
當鏈表為空時,新插入的節點就是鏈表的頭節點;
當鏈表不為空時,需要先遍歷到鏈表的尾部,然后將新節點連接到尾部節點的后面。

int tailInsert(LinkList* L, ElemType value) {LinkList s = (LinkList)malloc(sizeof(LNode));if (s == NULL){printf("內存分配失敗!\n");return -2;}s->data = value;s->next = NULL;  //因為新結點s要插入到鏈表尾部//若鏈表為空,新結點就是頭結點if (*L == NULL){*L = s;}else{//1.找到鏈表的尾結點LinkList p = *L;while (p->next != NULL) {p = p->next;}p->next = s;  //將新節點插入到尾結點后面}return 0; //插入成功
}

4. 插入

int insertLNode2(LinkList* L, int pos, ElemType value) {if (pos < 1) {printf("插入位置不合法!\n");return -1;}LinkList s = (LinkList)malloc(sizeof(LNode));if (s == NULL) {printf("內存分配失敗!\n");return -2;}s->data = value;if (pos == 1) {s->next = *L;*L = s;}else {LinkList p = *L;int i = 1;while (p != NULL && i < pos - 1) {p = p->next;i++;}if (p == NULL) {printf("插入位置不合法!\n");free(s);return -1;}s->next = p->next;p->next = s;}return 0;
}

5. 刪除

!不帶頭結點的單鏈表進行刪除結點操作需要分情況考慮:

若要刪除的是頭節點,需要直接更新頭指針;
若刪除的是其他節點,需要找到該節點的前一個節點。

int deleteNode(LinkList* L, int pos) {if (pos < 1){printf("刪除位置無效!\n");return -1;}if (*L == NULL){printf("當前鏈表為空!\n");return -2;}if (pos == 1)  //即刪除頭結點,(更新頭結點){LinkList temp = *L;*L = (*L)->next;free(temp);}else{LinkList p = *L;int i = 1;//找到第pos個結點while (p != NULL && i < pos - 1) {p = p->next;i++;}if (p == NULL || p->next == NULL){printf("刪除位置不合法!\n");return -1;}LinkList temp = p->next;p->next = temp->next;free(temp);}return 0;  //刪除成功
}

6. 按位查找

即:查找第pos個位置上的value值

int findValueByPos(LinkList L, int pos, ElemType* value) {if (pos < 1){printf("查找位置不合法!\n");return -1;}LinkList p = L;int i = 1;while (p != NULL && i < pos) {p = p->next;i++;}if (p == NULL){printf("查找位置超出鏈表長度!\n");return -1;}*value = p->data;return 0;
}

7. 按值查找

即:查找value值在鏈表的第pos個位置

int findPosByvalue(LinkList L,ElemType value) {LinkList p = L;int pos = 1;while (p != NULL) {if (p->data == value){return pos;}p = p->next;pos++;}return -1;  //查找失敗,未在該鏈表中找到該value值
}

8. 鏈表打印

void printLink2(LinkList L) {if (L == NULL) {printf("鏈表為空!\n");return;}LinkList s = L;while (s != NULL) {printf("%d ", s->data);s = s->next;}printf("\n--------------------------------\n");
}

9. 釋放空間

void freeList2(LinkList L) {LinkList p = L;while (p != NULL) {LinkList temp = p;p = p->next;free(temp);}
}

10. 測試代碼

int main() {//測試插入方法LinkList L1;InitLink2(&L1);insertLNode2(&L1, 1, 11);insertLNode2(&L1, 2, 22);insertLNode2(&L1, 3, 33);printLink2(L1);  // 11 22 33 freeList2(L1);// 測試頭插法LinkList L2;InitLink2(&L2);headInsert(&L2, 1);headInsert(&L2, 2);headInsert(&L2, 3);printLink2(L2);  // 3 2 1freeList2(L2);// 測試尾插法LinkList L3;InitLink2(&L3);tailInsert(&L3, 1);tailInsert(&L3, 2);tailInsert(&L3, 3);printLink2(L3);  // 1 2 3// 測試刪除deleteNode(&L3, 3);printf("刪除第三個結點后:");printLink2(L3);  //刪除第三個結點后:1 2//測試按值查找printf("數值1在第%d個位置\n", findPosByvalue(L3, 1));  // 數值1在第1個位置//測試按位查找ElemType value;findValueByPos(L3, 1, &value);printf("第1個位置的值為%d\n", value);  // 第1個位置的值為1freeList2(L3);return 0;
}

11. 完整代碼

#include<stdio.h>
#include<stdlib.h>
/*不帶頭結點的單鏈表
*/typedef int ElemType;
typedef struct LNode {ElemType data;  //數據域struct LNode* next;  //指針域
}LNode, * LinkList;// 操作1——不帶頭結點的初始化,即只需將頭指針初始化為NULL即可
void InitLink2(LinkList* L) {*L = NULL;
}// 操作2——不帶頭結點的插入操作
int insertLNode2(LinkList* L, int pos, ElemType value) {if (pos < 1) {printf("插入位置不合法!\n");return -1;}LinkList s = (LinkList)malloc(sizeof(LNode));if (s == NULL) {printf("內存分配失敗!\n");return -2;}s->data = value;if (pos == 1) {s->next = *L;*L = s;}else {LinkList p = *L;int i = 1;while (p != NULL && i < pos - 1) {p = p->next;i++;}if (p == NULL) {printf("插入位置不合法!\n");free(s);return -1;}s->next = p->next;p->next = s;}return 0;
}//操作2.1——不帶頭結點的頭插法建立單鏈表方法
int headInsert(LinkList* L, ElemType value) {LinkList s = (LinkList)malloc(sizeof(LNode));if (s == NULL){printf("內存分配失敗!\n");return -2;}s->data = value;s->next = *L;*L = s;  //更新頭結點指向新結點return 0;  //插入成功
}//操作2.3——不帶頭結點的尾插法建立單鏈表方法
/*
尾插法的核心思路是每次都將新節點插入到鏈表的末尾。
對于不帶頭結點的單鏈表,需要考慮鏈表為空的特殊情況。
當鏈表為空時,新插入的節點就是鏈表的頭節點;
當鏈表不為空時,需要先遍歷到鏈表的尾部,然后將新節點連接到尾部節點的后面。
*/
int tailInsert(LinkList* L, ElemType value) {LinkList s = (LinkList)malloc(sizeof(LNode));if (s == NULL){printf("內存分配失敗!\n");return -2;}s->data = value;s->next = NULL;  //因為新結點s要插入到鏈表尾部//若鏈表為空,新結點就是頭結點if (*L == NULL){*L = s;}else{//1.找到鏈表的尾結點LinkList p = *L;while (p->next != NULL) {p = p->next;}p->next = s;  //將新節點插入到尾結點后面}return 0; //插入成功
}// 操作3——刪除第pos個位置的值
/*
刪除操作需要分情況考慮,若要刪除的是頭節點,需要直接更新頭指針;
若刪除的是其他節點,需要找到該節點的前一個節點。
*/
int deleteNode(LinkList* L, int pos) {if (pos < 1){printf("刪除位置無效!\n");return -1;}if (*L == NULL){printf("當前鏈表為空!\n");return -2;}if (pos == 1)  //即刪除頭結點,(更新頭結點){LinkList temp = *L;*L = (*L)->next;free(temp);}else{LinkList p = *L;int i = 1;//找到第pos個結點while (p != NULL && i < pos - 1) {p = p->next;i++;}if (p == NULL || p->next == NULL){printf("刪除位置不合法!\n");return -1;}LinkList temp = p->next;p->next = temp->next;free(temp);}return 0;  //刪除成功
}// 操作4——按位查找:查找第pos個位置上的value值
int findValueByPos(LinkList L, int pos, ElemType* value) {if (pos < 1){printf("查找位置不合法!\n");return -1;}LinkList p = L;int i = 1;while (p != NULL && i < pos) {p = p->next;i++;}if (p == NULL){printf("查找位置超出鏈表長度!\n");return -1;}*value = p->data;return 0;
}// 操作5——按值查找:查找value值在鏈表的第pos個位置
int findPosByvalue(LinkList L,ElemType value) {LinkList p = L;int pos = 1;while (p != NULL) {if (p->data == value){return pos;}p = p->next;pos++;}return -1;  //查找失敗,未在該鏈表中找到該value值
}// 操作6——不帶頭結點的單鏈表打印操作
void printLink2(LinkList L) {if (L == NULL) {printf("鏈表為空!\n");return;}LinkList s = L;while (s != NULL) {printf("%d ", s->data);s = s->next;}printf("\n--------------------------------\n");
}// 操作7——釋放不帶頭結點鏈表內存
void freeList2(LinkList L) {LinkList p = L;while (p != NULL) {LinkList temp = p;p = p->next;free(temp);}
}int main() {//測試插入方法LinkList L1;InitLink2(&L1);insertLNode2(&L1, 1, 11);insertLNode2(&L1, 2, 22);insertLNode2(&L1, 3, 33);printLink2(L1);  // 11 22 33 freeList2(L1);// 測試頭插法LinkList L2;InitLink2(&L2);headInsert(&L2, 1);headInsert(&L2, 2);headInsert(&L2, 3);printLink2(L2);  // 3 2 1freeList2(L2);// 測試尾插法LinkList L3;InitLink2(&L3);tailInsert(&L3, 1);tailInsert(&L3, 2);tailInsert(&L3, 3);printLink2(L3);  // 1 2 3// 測試刪除deleteNode(&L3, 3);printf("刪除第三個結點后:");printLink2(L3);  //刪除第三個結點后:1 2//測試按值查找printf("數值1在第%d個位置\n", findPosByvalue(L3, 1));  // 數值1在第1個位置//測試按位查找ElemType value;findValueByPos(L3, 1, &value);printf("第1個位置的值為%d\n", value);  // 第1個位置的值為1freeList2(L3);return 0;
}

12. 運行截圖

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

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

相關文章

78.StringBuilder簡單示例 C#例子 WPF例子

利用 StringBuilder 提升字符串操作性能 在 C# 中&#xff0c;字符串是不可變的&#xff0c;這意味著每次修改字符串時都會創建一個新的對象。這種特性雖然保證了安全性&#xff0c;但在頻繁修改字符串的場景中會導致性能問題。StringBuilder 正是為解決這一問題而設計的。 什…

【數據集】社區天氣資訊網絡CoWIN-香港小時尺度氣象數據(含MATLAB處理代碼)

社區天氣資訊網絡CoWIN-香港小時尺度氣象數據 數據概述氣象變量說明數據提取(MATLAB全代碼)輸出WRF所需站點氣溫數據參考數據概述 官網-Community Weather Information Network (CoWIN) data policy CoWIN 提供 2010 - 2024 年 的數據下載,每年數據均可單獨下載。下載數據…

【JAVA架構師成長之路】【Redis】第14集:Redis緩存穿透原理、規避、解決方案

30分鐘自學教程&#xff1a;Redis緩存穿透原理與解決方案 目標 理解緩存穿透的成因及危害。掌握布隆過濾器、空值緩存等核心防御技術。能夠通過代碼實現請求攔截與緩存保護。學會限流降級、異步加載等應急方案。 教程內容 0~2分鐘&#xff1a;緩存穿透的定義與核心原因 定義…

尚硅谷爬蟲note15

一、當當網 1. 保存數據 數據交給pipelines保存 items中的類名&#xff1a; DemoNddwItem class DemoNddwItem(scrapy.Item): 變量名 類名&#xff08;&#xff09; book DemoNddwItem(src src, name name, price price)導入&#xff1a; from 項目名.items import 類…

LVGL直接解碼png圖片的方法

通過把png文件解碼為.C文件&#xff0c;再放到工程中的供使用&#xff0c;這種方式隨時速度快&#xff08;應為已經解碼&#xff0c;代碼中只要直接加載圖片數據顯示出來即可&#xff09;&#xff0c;但是不夠靈活&#xff0c;適用于哪些簡單又不經常需要更換UI的場景下使用。如…

【計算機網絡】Socket

Socket 是網絡通信的核心技術之一&#xff0c;充當應用程序與網絡協議棧之間的接口。 1. Socket 定義 Socket&#xff08;套接字&#xff09;是操作系統提供的 網絡通信抽象層&#xff0c;允許應用程序通過標準接口&#xff08;如 TCP/IP 或 UDP&#xff09;進行數據傳輸。它…

Apache XTable:在數據湖倉一體中推進數據互作性

Apache XTable 通過以多種開放表格式提供對數據的訪問&#xff0c;在增強互作性方面邁出了一大步。移動數據很困難&#xff0c;在過去&#xff0c;這意味著在為數據湖倉一體選擇開放表格式時&#xff0c;您被鎖定在該選擇中。一個令人興奮的項目當在數據堆棧的這一層引入互作性…

anolis8.9-k8s1.32-node-二進制部署

一、系統 # cat /etc/anolis-release Anolis OS release 8.9 # uname -r 5.10.134-18.an8.x86_64 二、從master上拷貝dockers及cri-docker相關文件 # groupadd docker # mkdir /etc/docker# scp -P 4033 root192.168.7.201:/etc/systemd/system/containerd.service /etc/s…

《AJAX:前端異步交互的魔法指南》

什么是AJAX AJAX&#xff08;Asynchronous JavaScript and XML&#xff0c;異步 JavaScript 和 XML&#xff09; 是一種用于創建異步網頁應用的技術&#xff0c;允許網頁在不重新加載整個頁面的情況下&#xff0c;與服務器交換數據并局部更新頁面內容。盡管名稱中包含 XML&…

Python 性能優化:從入門到精通的實用指南

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

利用 requestrepo 工具驗證 XML外部實體注入漏洞

1. 前言 在數字化浪潮席卷的當下&#xff0c;網絡安全的重要性愈發凸顯。應用程序在便捷生活與工作的同時&#xff0c;也可能暗藏安全風險。XXE&#xff08;XML外部實體&#xff09;漏洞作為其中的典型代表&#xff0c;攻擊者一旦利用它&#xff0c;便能竊取敏感信息、掌控服務…

FreeRTOS第17篇:FreeRTOS鏈表實現細節05_MiniListItem_t:FreeRTOS內存優化

文/指尖動聽知識庫-星愿 文章為付費內容,商業行為,禁止私自轉載及抄襲,違者必究!!! 文章專欄:深入FreeRTOS內核:從原理到實戰的嵌入式開發指南 1 為什么需要迷你列表項? 在嵌入式系統中,內存資源極其寶貴。FreeRTOS為滿足不同場景需求,設計了標準列表項(ListItem_…

Spring 無法解決循環依賴的 5 種場景

一、構造器注入引發的循環依賴 1. 問題復現 Component public class ServiceA {private final ServiceB serviceB;Autowiredpublic ServiceA(ServiceB serviceB) { // 構造器注入this.serviceB serviceB;} }Component public class ServiceB {private final ServiceA servic…

Core Vision Kit(基礎視覺服務)

文章目錄 一、Core Vision Kit簡介場景介紹約束與限制二、通用文字識別三、人臉檢測一、Core Vision Kit簡介 Core Vision Kit(基礎視覺服務)是機器視覺相關的基礎能力,例如通用文字識別(即OCR,Optical Character Recognition,也稱為光學字符識別)、人臉檢測、人臉比對…

第TR3周:Pytorch復現Transformer

&#x1f368; 本文為&#x1f517;365天深度學習訓練營中的學習記錄博客 &#x1f356; 原作者&#xff1a;K同學啊 Transformer通過自注意力機制&#xff0c;改變了序列建模的方式&#xff0c;成為AI領域的基礎架構 編碼器&#xff1a;理解輸入&#xff0c;提取上下文特征…

FreeRTOS 任務間通信機制:隊列、信號量、事件標志組詳解與實驗

1. FreeRTOS 消息隊列 1.1 簡介 ? 隊列是 任務間通信的主要形式&#xff0c;可用于在任務之間以及中斷與任務之間傳遞消息。隊列在 FreeRTOS 中具有以下關鍵特點&#xff1a; 隊列默認采用 先進先出 FIFO 方式&#xff0c;也可以使用 xQueueSendToFront()實現 LIFO。FreeRT…

【虛擬化】Docker Desktop 架構簡介

在閱讀前您需要了解 docker 架構&#xff1a;Docker architecture WSL 技術&#xff1a;什么是 WSL 2 1.Hyper-V backend 我們知道&#xff0c;Docker Desktop 最開始的架構的后端是采用的 Hyper-V。 Docker daemon (dockerd) 運行在一個 Linux distro (LinuxKit build) 中&…

Unity光照之Halo組件

簡介 Halo 組件 是一種用于在游戲中創建光暈效果的工具&#xff0c;主要用于模擬光源周圍的發光區域&#xff08;如太陽、燈泡等&#xff09;或物體表面的光線反射擴散效果。 核心功能 1.光暈生成 Halo 組件會在光源或物體的周圍生成一個圓形光暈&#xff0c;模擬光線在空氣…

Flink深入淺出之01:應用場景、基本架構、部署模式

Flink 1?? 一 、知識要點 &#x1f4d6; 1. Flink簡介 Apache Flink — Stateful Computations over Data StreamsApache Flink 是一個分布式大數據處理引擎&#xff0c;可對有界數據流和無界數據流進行有狀態的計算。Flink 能在所有常見集群環境中運行&#xff0c;并能以…

2025年【高壓電工】報名考試及高壓電工考試總結

隨著電力行業的快速發展&#xff0c;高壓電工成為確保電力系統安全穩定運行的重要一環。為了提高高壓電工的專業技能和安全意識&#xff0c;“安全生產模擬考試一點通”平臺特別整理了2025年高壓電工報名考試的相關信息及考試總結&#xff0c;并提供了一套完整的題庫&#xff0…