欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言中單鏈表的基本操作指南(增刪改查)

 更新時(shí)間:2021年09月07日 09:48:22   作者:若愛我菲、  
鏈表跟數(shù)組不同的是非連續(xù)存儲(chǔ)結(jié)構(gòu),也就是說實(shí)現(xiàn)鏈表需要一個(gè)指針,每用完一個(gè)節(jié)點(diǎn)指針指向下一個(gè)節(jié)點(diǎn),直至表尾,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中單鏈表的基本操作之增刪改查的相關(guān)資料,需要的朋友可以參考下

1.鏈表概述

鏈表是一種常見的數(shù)據(jù)結(jié)構(gòu)。它與常見的數(shù)組是不同的,使用數(shù)組時(shí)先要指定數(shù)組包含元素的個(gè)數(shù),即為數(shù)組的長(zhǎng)度,但是如果向這個(gè)數(shù)組中加入的元素超過了數(shù)組的大小時(shí),便不能將內(nèi)容全部保存。

鏈表這種存儲(chǔ)方式,其元素個(gè)數(shù)是不受限定的,當(dāng)進(jìn)行添加元素的時(shí)候存儲(chǔ)的個(gè)數(shù)就會(huì)隨之改變。

圖0

圖1

  鏈表一般有兩種形式,有空頭鏈表和無空頭鏈表。

圖2

在鏈表中有一個(gè)頭指針變量,這個(gè)指針變量保存一個(gè)地址,通過這個(gè)地址來找到這個(gè)鏈表,頭指針節(jié)點(diǎn)指向第一個(gè)節(jié)點(diǎn),在鏈表中每個(gè)節(jié)點(diǎn)包含兩個(gè)部分:數(shù)據(jù)部分和指針部分。雖然結(jié)構(gòu)體不能含有與本身類型相同的結(jié)構(gòu),但是可以含有之相同類型結(jié)構(gòu)的指針,這種定義是鏈表的基礎(chǔ),鏈表中每一項(xiàng)都包含在何處能找到下一項(xiàng)的信息。而最后一個(gè)節(jié)點(diǎn)的指針指向必須為空NULL,從鏈表的原理來看不用擔(dān)心鏈表的長(zhǎng)度會(huì)超出范圍這種問題。

2.鏈表的基本使用

2.0 準(zhǔn)備工作

使用鏈表時(shí),首先應(yīng)包含一些基本的頭文件,因?yàn)樯婕暗絻?nèi)存的操作和字符串的操作。

#include "stdio.h"				
#include "stdlib.h"				//提供malloc()和free()
#include "string.h"				//提供strcpy()等

malloc函數(shù)

其函數(shù)原型如下:

void *malloc(unsigned int size);

這個(gè)函數(shù)返回的是個(gè)void類型指針,所以在使用時(shí)應(yīng)注意強(qiáng)制類型轉(zhuǎn)換成需要的指針類型。

free函數(shù)

其函數(shù)原型如下:

void free(void *p);

這個(gè)函數(shù)是用來釋放指針p作指向的內(nèi)存區(qū)。

2.1 創(chuàng)建節(jié)點(diǎn)(結(jié)構(gòu)體)

struct Node
{
	int a;				//數(shù)據(jù)域
	struct Node* next;	//指針域(指向節(jié)點(diǎn)的指針)
};

2.2 全局定義鏈表頭尾指針 方便調(diào)用

struct Node* head= NULL;
struct Node* end = NULL;

2.3 創(chuàng)建鏈表,實(shí)現(xiàn)在鏈表中增加一個(gè)數(shù)據(jù)(尾添加)————增

void AddListTill(int a )
{
		//創(chuàng)建一個(gè)節(jié)點(diǎn)
		struct Node* temp=(struct Node*)malloc(sizeof(struct Node));		//此處注意強(qiáng)制類型轉(zhuǎn)換

		//節(jié)點(diǎn)數(shù)據(jù)進(jìn)行賦值
		temp->a=a;
		temp->next=NULL;		
		
		//連接分兩種情況1.一個(gè)節(jié)點(diǎn)都沒有2.已經(jīng)有節(jié)點(diǎn)了,添加到尾巴上
		if(NULL==head)
		{	

			head=temp;
		//	end=temp;
		}
		else
		{
		end->next=temp;
	//	end=temp;			//尾結(jié)點(diǎn)應(yīng)該始終指向最后一個(gè)
		}
		end=temp;			//尾結(jié)點(diǎn)應(yīng)該始終指向最后一個(gè)
}

AddListTill函數(shù)的功能是尾添加的方式在鏈表的尾部增加一個(gè)節(jié)點(diǎn),其中輸入的參數(shù)是這個(gè)節(jié)點(diǎn)的數(shù)據(jù)。首先創(chuàng)建一個(gè)節(jié)點(diǎn)并申請(qǐng)一個(gè)節(jié)點(diǎn)的內(nèi)存,之后對(duì)傳入節(jié)點(diǎn)的數(shù)據(jù)進(jìn)行賦值,注意尾添加的新節(jié)點(diǎn)的指針應(yīng)指向空;此時(shí)分兩種情況,1是鏈表中一個(gè)節(jié)點(diǎn)都沒有,那么這個(gè)節(jié)點(diǎn)既是頭結(jié)點(diǎn)也是尾結(jié)點(diǎn);2是已經(jīng)有節(jié)點(diǎn),那么新添加的節(jié)點(diǎn)將成為最后一個(gè)節(jié)點(diǎn),而之前的節(jié)點(diǎn)因?yàn)槌蔀榱说箶?shù)第二個(gè)節(jié)點(diǎn)了所以它的指針應(yīng)該指向新添加的節(jié)點(diǎn),之后全局變量尾結(jié)點(diǎn)應(yīng)該指向現(xiàn)在的節(jié)點(diǎn)(注意操作的先后順序不能變)。

2.4 遍歷鏈表 —————查

void ScanList()
{
	struct Node *temp =head;		//定義一個(gè)臨時(shí)變量來指向頭
	while (temp !=NULL)
	{
		printf("%d\n",temp->a);
		temp = temp->next;		//temp指向下一個(gè)的地址 即實(shí)現(xiàn)++操作
	}

}

ScanList函數(shù)的功能是遍歷這個(gè)鏈表,首先定義一個(gè)用于遍歷的臨時(shí)指針,用while循環(huán)實(shí)現(xiàn)遍歷輸出等操作。

2.5 查詢指定的節(jié)點(diǎn) (遍歷 一個(gè)個(gè)找)

struct Node* FindNode(int a )
{
	struct Node *temp =head;
	while(temp !=NULL)
	{
	if(a == temp->a)
	{
		return temp;
	}
	temp = temp->next;
	}
	//沒找到
		return NULL;
} 

FindNode函數(shù)的功能仍然是遍歷鏈表,只不過會(huì)對(duì)每個(gè)節(jié)點(diǎn)中的數(shù)據(jù)進(jìn)行一一判斷,若找到則返回該節(jié)點(diǎn),若沒找到則返回NULL。

2.6 鏈表清空——————全部刪除

void FreeList()
{
	//一個(gè)一個(gè)NULL
	struct Node *temp =head;		//定義一個(gè)臨時(shí)變量來指向頭
	while (temp !=NULL)
	{
	//	printf("%d\n",temp->a);
		struct Node* pt =temp;
		temp = temp->next;		//temp指向下一個(gè)的地址 即實(shí)現(xiàn)++操作
		free(pt);					//釋放當(dāng)前
	}
	//頭尾清空	不然下次的頭就接著0x10
	head =NULL;
	end =NULL;
}

FreeList函數(shù)仍是采用遍歷的方式一個(gè)一個(gè)的將節(jié)點(diǎn)內(nèi)存釋放,最后實(shí)現(xiàn)全部刪除的效果,但是要注意在最后應(yīng)該講頭尾節(jié)點(diǎn)至NULL否則下次的鏈表將會(huì)接著這次的頭尾。

2.7.在指定位置插入節(jié)點(diǎn) ————在指定位置增

void AddListRand(int index,int a)
{	

    if (NULL==head)
	{
		printf("鏈表沒有節(jié)點(diǎn)\n");
		return;
	}	
    struct Node* pt =FindNode(index);
	if(NULL==pt)    //沒有此節(jié)點(diǎn)
	{
		printf("沒有指定節(jié)點(diǎn)\n");
		return;
	}
    //有此節(jié)點(diǎn)
    //創(chuàng)建臨時(shí)節(jié)點(diǎn),申請(qǐng)內(nèi)存
	struct Node* temp =(struct Node *)malloc(sizeof(struct Node));
	//節(jié)點(diǎn)成員進(jìn)行賦值
	temp->a=a;
	temp->next=NULL;
	//連接到鏈表上 1.找到的節(jié)點(diǎn)在尾部 2.找到的節(jié)點(diǎn)在中間 
	if (pt == end)
	{
	//尾巴的下一個(gè)指向新插入的節(jié)點(diǎn)
	end->next=temp;
	//新的尾巴
	end=temp;
	}else
	{
	// 先連后面 (先將要插入的節(jié)點(diǎn)指針指向原來找到節(jié)點(diǎn)的下一個(gè))
	temp->next=pt->next;
	//后連前面
	pt->next=temp;
	}

}

首先要知道在指定節(jié)點(diǎn)插入的過程就像手拉手得人在一條線,這時(shí)來了一個(gè)新人,他要求站在甲之后,首先要找到甲的位置,如果鏈表為空或者沒有甲則無法插入,如果鏈表不為空并且甲在這個(gè)鏈表中,則還要看甲是在鏈表中間還是甲就在最后的尾巴上,如果在尾巴上則新插入的即為尾巴如圖1,若在甲乙之間則需要先連上后面乙再連上前面的甲,如圖2。

2.8尾刪除————?jiǎng)h

void DeleteListTail()
{ 
	if (NULL == end)
	{
		printf("鏈表為空,無需刪除\n");
		return;
	}
	//鏈表不為空 
	//鏈表有一個(gè)節(jié)點(diǎn)
	 if (head==end)
	 {
		 free(head);
		 head=NULL;
		 end=NULL; 
	 }
	 else
	 {
		//找到尾巴前一個(gè)節(jié)點(diǎn)
		 struct Node* temp =head;
		 while (temp->next!=end)
		 {
			 temp = temp->next;
		 }
		 //找到了,刪尾巴
		//釋放尾巴
		 free(end);
		 //尾巴遷移
		 end=temp;
		 //尾巴指針為NULL
		 end->next=NULL;
	 }

}

尾刪除的過程和前面一樣首先應(yīng)判斷這個(gè)鏈表是不是為空或者只有一個(gè)節(jié)點(diǎn),若只有一個(gè)節(jié)點(diǎn)則直接置NULL,若不為空,則先通過遍歷找到倒數(shù)第二個(gè)節(jié)點(diǎn),安徽將最后一個(gè)節(jié)點(diǎn)釋放內(nèi)存,再講倒數(shù)第二個(gè)節(jié)點(diǎn)設(shè)置為end,然后將它的指針指向NULL。

2.9 刪除頭——————?jiǎng)h

void DeleteListHead()
{	//記住舊頭
	struct Node* temp=head;
	//鏈表檢測(cè) 
	if (NULL==head)
	{
			printf("鏈表為空\(chéng)n");
			return;
	}

	head=head->next;//頭的第二個(gè)節(jié)點(diǎn)變成新的頭
	free(temp);

}

先定義一個(gè)臨時(shí)變量指向舊的頭,將頭的第二個(gè)記為新的頭指針head,之后將舊的頭釋放

2.10 刪除指定節(jié)點(diǎn)

void DeleteListRand(int a)
{

	//鏈表判斷 是不是沒有東西
	if(NULL==head)
	{
	printf("鏈表沒東西\n");
	return;
	}
    //鏈表有東西,找這個(gè)節(jié)點(diǎn)
	struct Node* temp =FindNode(a);
	if(NULL==temp)
	{
	printf("查無此點(diǎn)\n");
	return;
	}
	//找到了,且只有一個(gè)節(jié)點(diǎn)
	if(head==end)
	{
	free(head);
	head=NULL;
	end=NULL;
	}
	else if(head->next==end) //有兩個(gè)節(jié)點(diǎn)
	{
	//看是刪除頭還是刪除尾
	if(end==temp)
		{	DeleteListTail(); }
	else if(temp==head)
		{	DeleteListHead(); }	
	}
	else//多個(gè)節(jié)點(diǎn)
	{
		//看是刪除頭還是刪除尾
		if(end==temp)
			DeleteListTail();
		else if(temp==head)
			DeleteListHead();	
		else	//刪除中間某個(gè)節(jié)點(diǎn)
		{	//找要?jiǎng)h除temp前一個(gè),遍歷
			struct Node*pt =head;
			while(pt->next!=temp)
			{
			pt=pt->next;
			}
			//找到了
			//讓前一個(gè)直接連接后一個(gè) 跳過指定的即可
			 pt->next=temp->next;
			 free(temp);
		
		}
	}
	

}

情況與前面增加類似不再贅述,具體見圖

3. 測(cè)試主程序

下面是測(cè)試用的主程序,主要實(shí)現(xiàn)了鏈表的增刪查改等基本操作。

void main ()
{	
	struct Node *pFind ;
	//創(chuàng)建5個(gè)節(jié)點(diǎn)
	for(i=0;i<6;i++)
	AddListTill(i);
	
//	AddListRand(4,14);		//在指定位置4增加節(jié)點(diǎn)14
//	DeleteListTail();		//刪除一個(gè)尾結(jié)點(diǎn)
	DeleteListRand(4);		//刪除4節(jié)點(diǎn)
	ScanList();				//便利輸出鏈表
	FreeList();				//刪除鏈表
/*	pFind = FindNode(5);	//查找5節(jié)點(diǎn)

	if (pFind !=  NULL)
	{
		printf("找到%d\n",pFind->a);	//找到節(jié)點(diǎn)并且輸出該節(jié)點(diǎn)數(shù)據(jù)
	}
	else
	{
		printf("No Find!\n");
	}

*/

}

有關(guān)無空頭的單鏈表的基本操作就總結(jié)到這里,當(dāng)然還有雙鏈表等更復(fù)雜的數(shù)據(jù)結(jié)構(gòu),以及遍歷和查找的優(yōu)化算法也有待進(jìn)一步探索與學(xué)習(xí)。

總結(jié)

到此這篇關(guān)于C語(yǔ)言中單鏈表的增刪改查基本操作的文章就介紹到這了,更多相關(guān)C語(yǔ)言單鏈表增刪改查操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++中的Z字形變換問題

    C++中的Z字形變換問題

    將一個(gè)給定字符串?s?根據(jù)給定的行數(shù)?numRows?,以從上往下、從左到右進(jìn)行?Z?字形排列,這樣一個(gè)需求怎么實(shí)現(xiàn)呢,下面小編給大家?guī)砹薈++中的Z字形變換問題,需要的朋友可以參考下
    2022-07-07
  • OpenCV實(shí)現(xiàn)更改圖片顏色功能

    OpenCV實(shí)現(xiàn)更改圖片顏色功能

    這篇文章主要為大家詳細(xì)介紹了如何利用OpenCV實(shí)現(xiàn)更改圖片顏色的功能,文中代碼介紹詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • Qt網(wǎng)絡(luò)編程之TCP通信及常見問題

    Qt網(wǎng)絡(luò)編程之TCP通信及常見問題

    這篇文章主要為大家詳細(xì)介紹了Qt網(wǎng)絡(luò)編程之TCP通信及常見問題,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C語(yǔ)言實(shí)現(xiàn)洗牌發(fā)牌小程序

    C語(yǔ)言實(shí)現(xiàn)洗牌發(fā)牌小程序

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)洗牌發(fā)牌小程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • 利用Matlab制作一個(gè)賊簡(jiǎn)單的粒子圣誕樹

    利用Matlab制作一個(gè)賊簡(jiǎn)單的粒子圣誕樹

    圣誕節(jié)快到了,本文用Matlab繪制了圣誕樹祝你們圣誕節(jié)快樂,所以下面這篇文章主要給大家介紹了關(guān)于如何利用Matlab制作一個(gè)賊簡(jiǎn)單的粒子圣誕樹,需要的朋友可以參考下
    2022-12-12
  • C語(yǔ)言繪制余弦、正弦曲線

    C語(yǔ)言繪制余弦、正弦曲線

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言繪制余弦、正弦曲線的相關(guān)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • C++中繼承與組合的區(qū)別詳細(xì)解析

    C++中繼承與組合的區(qū)別詳細(xì)解析

    C++的“繼承”特性可以提高程序的可復(fù)用性。正因?yàn)椤袄^承”太有用、太容易用,才要防止亂用“繼承”
    2013-09-09
  • C++設(shè)計(jì)模式之組合模式

    C++設(shè)計(jì)模式之組合模式

    這篇文章主要介紹了C++設(shè)計(jì)模式之組合模式,本文講解什么是組合模式、組合模式的優(yōu)點(diǎn)、組合模式實(shí)例等內(nèi)容,需要的朋友可以參考下
    2014-09-09
  • Qt6遠(yuǎn)程連接MySQL數(shù)據(jù)庫(kù)的簡(jiǎn)單易上手版

    Qt6遠(yuǎn)程連接MySQL數(shù)據(jù)庫(kù)的簡(jiǎn)單易上手版

    在Qt應(yīng)用程序里,可實(shí)現(xiàn)遠(yuǎn)程MySQL服務(wù)器的連接操作,本文就來介紹一下Qt6遠(yuǎn)程連接MySQL數(shù)據(jù)庫(kù),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • 利用C++如何實(shí)現(xiàn)一個(gè)阻塞隊(duì)列詳解

    利用C++如何實(shí)現(xiàn)一個(gè)阻塞隊(duì)列詳解

    這篇文章主要給大家介紹了關(guān)于利用C++如何實(shí)現(xiàn)一個(gè)阻塞隊(duì)列的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10

最新評(píng)論