国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

這篇具有很好參考價(jià)值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

鏈表的引入

對于順序表存在一些缺陷:

  • 中間/頭部的插入刪除,時(shí)間復(fù)雜度為O(N) 。頭部插入需要挪動后面的元素

  • 增容需要申請新空間,拷貝數(shù)據(jù),釋放舊空間。會有不小的消耗。

  • 增容一般是呈2倍的增長,勢必會有一定的空間浪費(fèi)。例如當(dāng)前容量為100,滿了以后增容到200,我們再繼續(xù)插入了5個(gè)數(shù)據(jù),后面沒有數(shù)據(jù)插入了,那么就浪費(fèi)了95個(gè)數(shù)據(jù)空間

對于鏈表而言,能夠避免上述問題的出現(xiàn)。頭部插入數(shù)據(jù)不需要挪動大量的數(shù)據(jù),按需申請釋放空間,不會造成空間的浪費(fèi)。


鏈表的概念及結(jié)構(gòu)

概念:鏈表是一種物理存儲結(jié)構(gòu)上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的。

【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

現(xiàn)實(shí)中 數(shù)據(jù)結(jié)構(gòu)中(箭頭實(shí)際上并不存在,這里只是形象化):

【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

鏈表的種類有很多

以下情況組合起來就有8種鏈表結(jié)構(gòu):

單向或者雙向 :【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

帶頭或者不帶頭:【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

循環(huán)或者非循環(huán):【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

面對這么多種類的鏈表,我們該如何選擇?雖然有這么多的鏈表的結(jié)構(gòu),但是我們實(shí)際中最常用還是兩種結(jié)構(gòu):

【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

  1. 無頭單向非循環(huán)鏈表:結(jié)構(gòu)簡單,一般不會單獨(dú)用來存數(shù)據(jù)。實(shí)際中更多是作為其他數(shù)據(jù)結(jié)構(gòu)的子結(jié)構(gòu),如哈希桶、圖的鄰接表等等
  2. 帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲數(shù)據(jù)。實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會發(fā)現(xiàn)結(jié)構(gòu)會帶來很多優(yōu)勢,實(shí)現(xiàn)反而簡單了,后面我們代碼實(shí)現(xiàn)了就知道了

話不多說,直接進(jìn)入我們單鏈表的實(shí)現(xiàn):

單鏈表的接口我們需要實(shí)現(xiàn):

  • 打印銷毀

  • 頭插尾插創(chuàng)建新結(jié)點(diǎn)(由于后面會頻繁使用,故將其封裝成函數(shù))

  • 尾刪頭刪查找

  • 在pos之前插入、在pos之后插入

  • 刪除pos、刪除pos之后的位置

我們還是老樣子,通過三個(gè)部分組成:

**SList.h:**包括頭文件的引用,結(jié)構(gòu)體的聲明定義,接口函數(shù)的聲明。

**SList.c:**對SList.h中接口函數(shù)進(jìn)行實(shí)現(xiàn)。

**test.c:**主函數(shù)進(jìn)行測試:通過void TestSList()函數(shù)對SList.c的函數(shù)進(jìn)行調(diào)用,測試有沒有錯(cuò)誤。

注意:對于一些問題的所在,我已經(jīng)通過注釋進(jìn)行相關(guān)說明。注釋才是精髓。

SList.h

#define _CRT_SECURE_NO_WARNINGS

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType data;
	struct SLTNode* next;
}SLTNode;

//打印
void SListPrint(SLTNode* phead);

//創(chuàng)建新結(jié)點(diǎn)
SLTNode* BuySLTNode(SLTDataType x);

//銷毀
void SListDestory(SLTNode** pphead);

//頭插
void SListPushFront(SLTNode** pphead, SLTDataType x);

//尾插
void SListPushBack(SLTNode** pphead, SLTDataType x);

//尾刪
void SListPopBack(SLTNode**pphead);

//頭刪
void SListPopFront(SLTNode**pphead);

//查找
SLTNode* SListFind(SLTNode* pphead,SLTDataType x);

//在pos之前插入
void SListInsert(SLTNode** pphead,SLTNode*pos,SLTDataType x);

//在pos之后插入
void SListInsertAfter(SLTNode* pos, SLTDataType x);

//刪除pos
void SListErase(SLTNode** pphead,SLTNode*pos);


//刪除pos后面位置,了解
void SListEraseAfter(SLTNode* pos);

【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

SList.c

#define _CRT_SECURE_NO_WARNINGS

#include "SList.h"
//打印
void SListPrint(SLTNode* phead)
{
	//phead不需要斷言。因?yàn)閜head有可能有空,沒有數(shù)據(jù)
	//而順序表的結(jié)構(gòu)體不可能為空,所以要進(jìn)行斷言
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");


}

//創(chuàng)建新結(jié)點(diǎn)
SLTNode* BuySLTNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("mail fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

//銷毀
void SListDestory(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

//頭插
void SListPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}


//尾插——有無結(jié)點(diǎn)。需要找前一個(gè)
void SListPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);

	//空,改變的是SListNode*,需要二級指針

	//非空。尾插要改變的是結(jié)構(gòu)體SListNode,只需要結(jié)構(gòu)體的指針

	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//找尾
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

//尾刪——有無結(jié)點(diǎn)。需要找前一個(gè)
void SListPopBack(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* tail = *pphead;
	SLTNode* prev = NULL;
	assert(*pphead != NULL);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		prev->next = NULL;
		free(tail);
		tail = NULL;
		/*while (tail->next->next!=NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;*/

	}
}

//頭刪
void SListPopFront(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	/*if (*pphead == NULL)
	{
		return;
	}*/
	SLTNode* del = *pphead;
	*pphead = (*pphead)->next;
	free(del);
	del = NULL;
}

//查找
SLTNode* SListFind(SLTNode* pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* cur = pphead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}


//在pos之前插入,需要找前一個(gè)
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SListPushFront(pphead, x);
	}
	else
	{
		SLTNode* newnode = BuySLTNode(x);
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
			assert(prev);
		}
		prev->next = newnode;
		newnode->next = pos;
	}
}


//在pos后插入
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}


//刪除pos位置,需要找前一個(gè)
void SListErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SListPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
			//檢查pos不是鏈表中的結(jié)點(diǎn)
			assert(prev);
		}
		prev->next = pos->next;
		free(pos);
	}
}


//刪除pos后面位置
void SListEraseAfter(SLTNode* pos)
{
	assert(pos);
	if (pos->next == NULL)
	{
		return;
	}
	else
	{
		SLTNode* next = pos->next;
		pos->next = next->next;
		free(next);

	}
}

【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表

test.c

#define _CRT_SECURE_NO_WARNINGS

#include "SList.h"


//頭插、頭刪
void TestSList1()
{
	SLTNode* plist = NULL;
	SListPushFront(&plist, 1);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 3);
	SListPushFront(&plist, 4);
	SListPrint(plist);

	SListPopFront(&plist);
	SListPrint(plist);
	SListPopFront(&plist);
	SListPrint(plist);
	SListPopFront(&plist);
	SListPrint(plist);
	SListPopFront(&plist);
	SListPrint(plist);
	SListPopFront(&plist);
	SListPrint(plist);

	SListDestory(&plist);

}

//尾插、尾刪
void TestSList2()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);
	SListPrint(plist);

	SListPopBack(&plist);
	SListPopBack(&plist);
	SListPopBack(&plist);
	SListPopBack(&plist);
	SListPopBack(&plist);

	SListDestory(&plist);
}


//查找、在pos之前插入
void TestSList3()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);
	SListPrint(plist);

	SLTNode* pos = SListFind(plist, 3);
	if (pos)
	{
		//修改
		pos->data *= 10;
		printf("找到了\n");
	}
	else
	{
		printf("找不到\n");
	}

	pos = SListFind(plist, 1);
	if (pos)
	{
		SListInsert(&plist, pos, 10);
	}


	SListPrint(plist);
	SListDestory(&plist);

}

//刪除pos位置、刪除pos后面的位置
void TestSList4()
{

	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);
	SListPrint(plist);

	SLTNode* pos = SListFind(plist, 3);
	if (pos)
	{
		SListErase(&plist, pos);
	}
	SListPrint(plist);

	pos = SListFind(plist, 1);
	if (pos)
	{
		SListErase(&plist, pos);
	}
	SListPrint(plist);
}


int main()
{
	//TestSList1();
	//TestSList2();
	//TestSList3();
	TestSList4();
	return 0;
}

【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表


以上就是單鏈表的相關(guān)操作,我們不難發(fā)現(xiàn),單鏈表的優(yōu)勢在于頭插頭刪

而對于一些操作:如尾插尾刪而言,我們都需要去找前一個(gè)位置,這是比較麻煩的。單鏈表我們就先介紹到這里了。

這里同時(shí)也有一個(gè)問題存在:

刪除當(dāng)前位置我們需要去找前一個(gè)位置,這效率是比較低的,我們?nèi)绾胃倪M(jìn)這個(gè)問題?

找pos位置刪除,而就是不找前一個(gè)位置(即要求是O(1)):替換法刪除,把pos的值和下一個(gè)節(jié)點(diǎn)的值進(jìn)行交換,再把pos進(jìn)行釋放掉。但是有一個(gè)缺陷:pos不能是尾節(jié)點(diǎn)。尾節(jié)點(diǎn)沒有下一項(xiàng)。

那如果在pos位置之前插入,要求為O(1)呢:

直接插入到pos后面,然后進(jìn)行交換。


總結(jié)

  • 我們從鏈表的引入開始,了解了為什么鏈表會出現(xiàn),同時(shí)認(rèn)識了鏈表的概念和結(jié)構(gòu)。本篇博客主要介紹了單鏈表的操作,以及解決了一個(gè)問題。本次就先到這里結(jié)束了。

【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表文章來源地址http://www.zghlxwxcb.cn/news/detail-408822.html

到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)與算法】鏈表的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)---順序表,鏈表

    數(shù)據(jù)結(jié)構(gòu)---順序表,鏈表

    目錄 前言 線性表 線性表的概念 順序表 順序表的概念 順序表的結(jié)構(gòu) 接口實(shí)現(xiàn) 相關(guān)面試題分析 順序表的問題及思考 鏈表 鏈表的概念及結(jié)構(gòu) 鏈表的分類 單鏈表的實(shí)現(xiàn)? 接口實(shí)現(xiàn)? 鏈表面試題 雙向鏈表 順序表和鏈表的區(qū)別 ? ? ? ? 這篇文章主要講順序表和鏈表,有幾點(diǎn)需要

    2024年02月16日
    瀏覽(21)
  • 【數(shù)據(jù)結(jié)構(gòu)】順序表和鏈表

    【數(shù)據(jù)結(jié)構(gòu)】順序表和鏈表

    線性表(linear list)是n個(gè)具有相同特性的數(shù)據(jù)元素的有限序列。 線性表是一種在實(shí)際中廣泛使 用的數(shù)據(jù)結(jié)構(gòu),常見的線性表:順序表、鏈表、棧、隊(duì)列、字符串... 線性表在邏輯上是線性結(jié)構(gòu),也就說是連續(xù)的一條直線。但是在物理結(jié)構(gòu)上并不一定是連續(xù)的, 線性表在物理上

    2024年01月20日
    瀏覽(156)
  • 數(shù)據(jù)結(jié)構(gòu)(二)----線性表(順序表,鏈表)

    數(shù)據(jù)結(jié)構(gòu)(二)----線性表(順序表,鏈表)

    目錄 1.線性表的概念 2.線性表的基本操作 3.存儲線性表的方式 (1)順序表 ?順序表的概念 ?順序表的實(shí)現(xiàn) 靜態(tài)分配: 動態(tài)分配: 順序表的插入: 順序表的刪除: 順序表的按位查找: 順序表的按值查找: 順序表的特點(diǎn): (2)單鏈表 ?單鏈表的實(shí)現(xiàn) 不帶頭結(jié)點(diǎn)的單鏈表

    2024年04月16日
    瀏覽(40)
  • 數(shù)據(jù)結(jié)構(gòu)2:順序表和鏈表

    數(shù)據(jù)結(jié)構(gòu)2:順序表和鏈表

    目錄 1.線性表 2.順序表 2.1概念及結(jié)構(gòu) 2.2接口實(shí)現(xiàn) 2.3數(shù)據(jù)相關(guān)面試題 2.4順序表的問題及思考 3.鏈表 3.1鏈表的概念及結(jié)構(gòu) 3.2鏈表的分類 3.3鏈表的實(shí)現(xiàn) 3.4鏈表面試題 3.5雙向鏈表的實(shí)現(xiàn) 4.順序表和鏈表的區(qū)別 線性表(linear list)是具有相同特征的數(shù)據(jù)元素的有限序列。線性表是

    2023年04月17日
    瀏覽(93)
  • 《數(shù)據(jù)結(jié)構(gòu)》實(shí)驗(yàn)報(bào)告二:順序表 鏈表

    《數(shù)據(jù)結(jié)構(gòu)》實(shí)驗(yàn)報(bào)告二:順序表 鏈表

    1、掌握線性表中元素的 前驅(qū)、后續(xù) 的概念。 2、掌握順序表與鏈表的 建立 、 插入 元素、 刪除 表中某元素的算法。 3、對線性表相應(yīng)算法的 時(shí)間復(fù)雜度 進(jìn)行分析。 4、理解順序表、鏈表數(shù)據(jù)結(jié)構(gòu)的特點(diǎn)( 優(yōu)缺點(diǎn) )。 說明以下概念 1、線性表: ? ? ? ? 具有 相同特性 的數(shù)

    2024年02月08日
    瀏覽(31)
  • 常見的數(shù)據(jù)結(jié)構(gòu)(順序表、順序表、鏈表、棧、隊(duì)列、二叉樹)

    常見的數(shù)據(jù)結(jié)構(gòu)(順序表、順序表、鏈表、棧、隊(duì)列、二叉樹)

    線性表(Linear List) ? ? 1.什么是線性表 ? ? 2.線性表的特點(diǎn) ? ? 3.線性表的基本運(yùn)算 順序表 ? ? 1.什么是順序表 ? ? 2.時(shí)間復(fù)雜度: 鏈表 ? ? 1.什么是鏈表 ? ? 2.單向鏈表 ? ? 3. 雙向鏈表 ? ? 4.ArrayList和LinkedList的使用 棧Stack ? ? 1.什么是棧 ? ? 2.棧的基本方法 隊(duì)列Queue

    2024年02月13日
    瀏覽(52)
  • 數(shù)據(jù)結(jié)構(gòu),隊(duì)列,順序表隊(duì)列,鏈表隊(duì)列

    ????????隊(duì)列是一種常見的數(shù)據(jù)結(jié)構(gòu),它具有先進(jìn)先出(First-In-First-Out,F(xiàn)IFO)的特性,類似于排隊(duì)等候的場景。以下是隊(duì)列的要點(diǎn): 1. 定義:隊(duì)列是一種線性數(shù)據(jù)結(jié)構(gòu),由一系列元素組成,可以進(jìn)行插入和刪除操作。插入操作(稱為入隊(duì))只能在隊(duì)列的末尾進(jìn)行,刪除操

    2024年02月11日
    瀏覽(19)
  • 數(shù)據(jù)結(jié)構(gòu):2_順序表和鏈表

    數(shù)據(jù)結(jié)構(gòu):2_順序表和鏈表

    線性表(linear list)是n個(gè)具有相同特性的數(shù)據(jù)元素的有限序列。 線性表是一種在實(shí)際中廣泛使用的數(shù)據(jù)結(jié)構(gòu), 常見的線性表:順序表、鏈表、棧、隊(duì)列、字符串… 線性表在邏輯上是線性結(jié)構(gòu),也就說是連續(xù)的一條直線。但是在物理結(jié)構(gòu)上并不一定是連續(xù)的 ,線性表在物理上

    2024年01月18日
    瀏覽(100)
  • 數(shù)據(jù)結(jié)構(gòu)順序表和鏈表(超詳細(xì))

    數(shù)據(jù)結(jié)構(gòu)順序表和鏈表(超詳細(xì))

    線性表 ( linear list ) 是 n 個(gè)具有相同特性的數(shù)據(jù)元素的有限序列。 線性表是一種在實(shí)際中廣泛使 用的數(shù)據(jù)結(jié)構(gòu), 常見的線性表:順序表、鏈表、棧、隊(duì)列、字符串 ... 線性表在邏輯上是線性結(jié)構(gòu),也就說是連續(xù)的一條直線。但是在物理結(jié)構(gòu)上并不一定是連續(xù)的, 線性表在

    2024年02月13日
    瀏覽(108)
  • 【數(shù)據(jù)結(jié)構(gòu)初階】順序表和鏈表(1)

    【數(shù)據(jù)結(jié)構(gòu)初階】順序表和鏈表(1)

    線性表(linear list) 是n個(gè)具有相同特性的數(shù)據(jù)元素的有限序列。 線性表是一種在實(shí)際中廣泛使 用的數(shù)據(jù)結(jié)構(gòu),常見的線性表:順序表、鏈表、棧、隊(duì)列、字符串… 線性表在邏輯上是線性結(jié)構(gòu),也就說是連續(xù)的一條直線。但是在物理結(jié)構(gòu)上并不一定是連續(xù)的,線性表在物理上

    2024年02月08日
    瀏覽(1598)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包