最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言實現(xiàn)順序表的全操作詳解

 更新時間:2022年04月23日 15:36:09   作者:風&646  
順序表,全名順序存儲結(jié)構(gòu),是線性表的一種,線性表用于存儲邏輯關(guān)系為“一對一”的數(shù)據(jù),順序表自然也不例外,不僅如此,順序表對數(shù)據(jù)的物理存儲結(jié)構(gòu)也有要求,跟隨下文來具體了解吧

線性表

線性表(linear list)是n個具有相同特性的數(shù)據(jù)元素的有限序列。線性表是一種在實際中廣泛使用的數(shù)據(jù)結(jié)構(gòu),常見的線性表有:順序表、鏈表、棧、隊列、字符串等。

線性表在邏輯上是線性結(jié)構(gòu),也就是連續(xù)的一條直線。但在物理結(jié)構(gòu)上并不一定是連續(xù)的,線性表在物理上存儲時,通常以數(shù)組和鏈式的形式存儲。

順序表

順序表是用一段物理連續(xù)地址的存儲單元依次存儲數(shù)據(jù)元素的線性結(jié)構(gòu),一般情況采用數(shù)組存儲。在數(shù)組上面完成數(shù)據(jù)的增刪查改。

一般情況下,順序表可以分為一下兩種:

1.靜態(tài)順序表:使用定長數(shù)組存儲元素。

2.動態(tài)順序表:使用動態(tài)開辟的數(shù)組存儲。

順序表接口實現(xiàn)

靜態(tài)順序表只適用于確定知道需要存儲多少數(shù)據(jù)的場景。靜態(tài)順序表不夠靈活。所以我們基本都使用動態(tài)順序表,根據(jù)需要空間的多少來分配大小,所有下面我們實現(xiàn)動態(tài)順序表。

先定義一個結(jié)構(gòu)體:

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;     //存儲數(shù)據(jù)個數(shù)
	int capacity; //容量空間大小
}SeqList;

1.順序表初始化

void SeqListInit(SeqList* ps);
void SeqListInit(SeqList* ps)
{
	assert(ps); //檢查指針的有效性
	ps->a = NULL; //不知道開多大的空間,就先賦值NULL
	ps->capacity = ps->size = 0;
}

我們在給ps->a開辟空間的時候,還可以以如下方式開辟,這樣甚至更簡單一點(開辟完空間后需要檢查空間的有效性),但這兩種都可以。

STDataType*tmp=(STDataType*)malloc(sizeof(SeqList)*2);

2.順序表空間增容

//檢查空間,如果滿了,就進行增容
void SeqListCheckCapacity(SeqList* ps);
void SeqListCheckCapacity(SeqList* ps)
{
	assert(ps);
	if (ps->capacity == ps->size)
	{
		size_t newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = realloc(ps->a, sizeof(SLDataType) * newcapacity);
		if (tmp == NULL)
		{
			printf("CheckCapacity::%s\n", strerror(errno));//若空間開辟失敗,則打印開辟失敗的原因
			exit(-1);//若空間開辟失敗,則直接終止程序
		}
		else
		{
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
	}
}

1.此處realloc空間,如果容量不夠,我們就將容量擴展為原來的兩倍,但是我們一開始初始化的空間有可能是0,所以我們應(yīng)該把這種情況考慮進去。

2.realloc空間可能因為一些原因而失敗,所以要對開辟的空間進行檢查,即判斷申請的空間是否為空(NULL)。

3.順序表打印

//順序表打印
void SeqListPrint(SeqList* ps);
void SeqListPrint(SeqList* ps)
{
	assert(ps);
	for (int i = 0;i < ps->size;++i)//依次遍歷,打印出每一個信息
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

4.尾插數(shù)據(jù)

//順序表尾插
void SeqListPushBack(SeqList* ps, SLDataType x);
void SeqListPushBack(SeqList* ps, SLDataType x)
{
	assert(ps);
	SeqListCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}

5.尾刪數(shù)據(jù)

//順序表尾刪
void SeqListPopBack(SeqList* ps);
void SeqListPopBack(SeqList* ps)
{
	assert(ps);
	if (ps->size > 0)//防止尾刪將數(shù)據(jù)刪完了,size出現(xiàn)負數(shù)
	{
		ps->size--;
	}
}

注意:size減的時候一定要加條件限制,防止下標出現(xiàn)負數(shù)。

6.頭插數(shù)據(jù)

//順序表頭插
void SeqListPushFront(SeqList* ps, SLDataType x);
void SeqListPushFront(SeqList* ps, SLDataType x)
{
	assert(ps);
	SeqListCheckCapacity(ps);//檢查空間容量
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];
		--end;
	}
	ps->a[0] = x;
	ps->size++;
}

7.頭刪數(shù)據(jù)

//順序表頭刪
void SeqListPopFront(SeqList* ps);
void SeqListPopFront(SeqList* ps)
{
	assert(ps);
	//依次挪動數(shù)據(jù)覆蓋刪除
	if (ps->size > 0)//確保有數(shù)據(jù)可刪除,防止下標出現(xiàn)負數(shù)
	{
		int begin = 1;
		while (begin < ps->size)
		{
			ps->a[begin - 1] = ps->a[begin];
			++begin;
		}
		ps->size--;
	}
}

注意:頭刪一定要保證下標大于0,不然刪掉一個下標減一下,當下標減為負數(shù)的時候,程序就會出錯。頭刪的時候數(shù)據(jù)從前向后數(shù)據(jù)依次向前覆蓋一位。

8.在pos下標處插入數(shù)據(jù)

//順序表在pos位置插入數(shù)據(jù)
void SeqListInsert(SeqList* ps, size_t pos, SLDataType x);
void SeqListInsert(SeqList* ps, size_t pos, SLDataType x)
{
	assert(ps);
	if (pos > ps->size)
	{
		printf("pos越界\n");
		return;
	}
	SeqListCheckCapacity(ps);
	size_t end = ps->size;
	while (end > pos)
	{
		ps->a[end] = ps->a[end - 1];
		--end;
	}
	ps->a[pos] = x;
	ps->size++;
}

這里需要特別注意一下下標的問題,如下圖:

在這里循環(huán)有兩種寫法,一種如上,還有一種就是下邊這種。

int end =ps->size-1;
while(end>=(int)pos)
{
    ps->a[end+1]=ps->a[end];
    --end;
}

注意:對比以上兩種寫法,我們注意到了pos和end的類型。因為坐標不可能為負數(shù),所以pos為size_t類型。對于第二種情況:int end=ps->size-1時,循環(huán)執(zhí)行到最后end的值會變?yōu)?1,但pos的類型為size_t,所以當end與pos比較的時候,會發(fā)生整形提升,使無符號的end整形提升為有符號的數(shù)字和pos比較,所以while條件成立,會繼續(xù)循環(huán),導(dǎo)致越界訪問內(nèi)存。對于這種我們的解決方法是將pos強制轉(zhuǎn)換為int類型,如上訴代碼。

對于第一種情況: int end=ps->size,循環(huán)執(zhí)行到最后end的值為0,為無符號數(shù),因此剛好完美的進行了移動覆蓋,不會出現(xiàn)越界訪問的情況。所以我們推薦使用第一種方法。

9.刪除pos下標處數(shù)據(jù)

//順序表刪除pos位置的數(shù)據(jù)
void SeqListErase(SeqList* ps, size_t pos);
void SeqListErase(SeqList* ps, size_t pos)
{
	assert(ps);
	if (pos >= ps->size)
	{
		printf("pos越界\n");
		return;
	}
	size_t begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		++begin;
	}
	ps->size--;
}

10.數(shù)據(jù)查找

依次遍歷數(shù)據(jù)查找,若找到了對應(yīng)的數(shù)據(jù),則返回它的下標。若找不到,則返回-1.

//順序表查找
int SeqListFind(SeqList* ps, SLDataType x);
int SeqListFind(SeqList* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0;i < ps->size;++i)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

11.順序表摧毀

當我們使用動態(tài)申請空間時,使用完后,一定要釋放動態(tài)開辟的內(nèi)存。否則可能會造成內(nèi)存泄漏。

//順序表銷毀
void SeqListDestroy(SeqList* ps);
void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

到此這篇關(guān)于C語言實現(xiàn)順序表的全操作詳解的文章就介紹到這了,更多相關(guān)C語言順序表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++詳細講解模擬實現(xiàn)位圖和布隆過濾器的方法

    C++詳細講解模擬實現(xiàn)位圖和布隆過濾器的方法

    位圖(bitset)是一種常用的數(shù)據(jù)結(jié)構(gòu),常用在給一個很大范圍的數(shù),判斷其中的一個數(shù)是不是在其中。在索引、數(shù)據(jù)壓縮方面有很大的應(yīng)用。布隆過濾器是由布隆提出的,它實際上是一個很長的二進制向量和一系列隨機映射函數(shù)。布隆過濾器可以用于檢索一個元素是否在一個集合中
    2022-06-06
  • C語言詳細講解樹狀數(shù)組與線段樹

    C語言詳細講解樹狀數(shù)組與線段樹

    顧名思義,樹狀數(shù)組就是用數(shù)組來模擬樹形結(jié)構(gòu)唄。那么衍生出一個問題,為什么不直接建樹,因為樹狀數(shù)組能處理的問題就沒必要建樹。線段樹是一種二叉搜索樹,與區(qū)間樹相似,它將一個區(qū)間劃分成一些單元區(qū)間,每個單元區(qū)間對應(yīng)線段樹中的一個葉結(jié)點
    2022-04-04
  • 淺談C/C++中的static與extern關(guān)鍵字的使用詳解

    淺談C/C++中的static與extern關(guān)鍵字的使用詳解

    本篇文章是對C/C++中的static與extern關(guān)鍵字的使用進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C指針原理教程之編譯原理-小型計算器實現(xiàn)

    C指針原理教程之編譯原理-小型計算器實現(xiàn)

    本文給大家分享的是如何使用C語言編寫一個小型計算器的實例代碼,有需要的小伙伴可以參考下
    2019-02-02
  • C++中的friend友元函數(shù)詳細解析

    C++中的friend友元函數(shù)詳細解析

    友元可以是一個函數(shù),該函數(shù)被稱為友元函數(shù);友元也可以是一個類,該類被稱為友元類。友元函數(shù)的特點是能夠訪問類中的私有成員的非成員函數(shù)。友元函數(shù)從語法上看,它與普通函數(shù)一樣,即在定義上和調(diào)用上與普通函數(shù)一樣
    2013-09-09
  • Qt數(shù)據(jù)庫應(yīng)用之實現(xiàn)通用數(shù)據(jù)庫采集

    Qt數(shù)據(jù)庫應(yīng)用之實現(xiàn)通用數(shù)據(jù)庫采集

    這篇文章主要為大家介紹了Qt中是如何實現(xiàn)通用數(shù)據(jù)庫采集的,文中的示例代碼講解詳細,對我們學(xué)習Qt有一定幫助,感興趣的小伙伴可以了解一下
    2022-03-03
  • c++中std::placeholders的使用方法

    c++中std::placeholders的使用方法

    std::placeholders?是 C++ 標準庫中的一個工具,用于在函數(shù)對象綁定時創(chuàng)建占位符,本文就來詳細的介紹一下,具有一定的參考價值,感興趣的可以了解一下
    2025-02-02
  • C++利用libcurl庫實現(xiàn)多線程文件下載

    C++利用libcurl庫實現(xiàn)多線程文件下載

    這篇文章主要為大家詳細介紹了C++如何利用libcurl庫實現(xiàn)多線程文件下載,文章的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考下
    2024-01-01
  • C++的最短路徑的弗洛伊德算法案例講解

    C++的最短路徑的弗洛伊德算法案例講解

    這篇文章主要介紹了C++的最短路徑的弗洛伊德算法案例講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 基于C++實現(xiàn)酒店管理系統(tǒng)

    基于C++實現(xiàn)酒店管理系統(tǒng)

    這篇文章主要為大家詳細介紹了基于C++實現(xiàn)酒店管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論

项城市| 利辛县| 喜德县| 松桃| 林西县| 洱源县| 湖北省| 赤峰市| 德兴市| 五家渠市| 九龙坡区| 闸北区| 安岳县| 盖州市| 嫩江县| 英德市| 什邡市| 天津市| 香格里拉县| 天台县| 通许县| 内乡县| 中江县| 分宜县| 徐闻县| 营山县| 屯昌县| 龙里县| 安福县| 汾西县| 新河县| 英超| 乐东| 威信县| 百色市| 康平县| 疏勒县| 海南省| 东乡族自治县| 博兴县| 巴彦淖尔市|