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

C語言編程簡單卻重要的數(shù)據(jù)結(jié)構(gòu)順序表全面講解

 更新時間:2021年10月22日 14:48:28   作者:高郵吳少  
這篇文章主要為大家介紹了C語言編程中非常簡單卻又非常重要的數(shù)據(jù)結(jié)構(gòu)順序表的全面講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助

前言

本文主要介紹順序表的定義和常見靜態(tài)順序表的用法。

一、線性表定義

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

二、順序表實現(xiàn)

1概念及結(jié)構(gòu)

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

順序表一般可表示為:

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

我們以簡單的靜態(tài)順序表進行引例(與動態(tài)順序表接口函數(shù)思想是一樣的)
代碼如下(示例):

#define N 10//這里定義宏是為了方便將來如果需要更改空間的大小,而代碼中用到的10過于多要更改多次,宏定義直接改N大小即可
typedef int SQDataType;//這里順序表10個空間都是int型,如果將來要改變類型,可以在這里把int改為所需類型
struct SeqList//單個數(shù)據(jù)直接定義變量,多個數(shù)據(jù)定義結(jié)構(gòu)體
{
	SQDataType a[N];//順序表有10個空間可進行存儲
	int size;//順序表存了幾個數(shù)據(jù)(有10個空間不一定就存10個數(shù)據(jù))
};

ps:順序表的一些要求:
1.連續(xù)的物理空間存儲-用的是數(shù)組
2.數(shù)據(jù)必須是從頭開始,依次存儲

2靜態(tài)順序表

2.1實現(xiàn)順序表接口,第一步要對順序表進行初始化

代碼如下(示例):

#include<stdio.h>
#include<string.h>//memset函數(shù)頭文件
//增刪查改等接口函數(shù)
void SeqListInit(struct SeqList *ps)
{
	memset(ps->a, 0, sizeof(SQDataType)*N);//memset是一個初始化函數(shù)
	//sl.a表示按字節(jié)初始化
	//0表示初始化為0
	//sizeof(SQDataType)表示數(shù)組內(nèi)每個元素大小(之前定義了SQDataType=int),N表示數(shù)組內(nèi)共有N個元素,兩者相乘是數(shù)組大小
	ps->size = 0;
}
void TestSeqList1()
{
	struct SeqList sl;//sl是實參,上面的ps是形參,為了實參和形參可以相互影響,這里用的是傳址調(diào)用
	SeqListInit(&sl);
}
int main()
{
	TestSeqList1();
	return 0;
}
//ps:如果這里你覺得寫struct SeqList sl煩,你可以這樣改進代碼(這里和2.1代碼對應(yīng))
//typedef struct SeqList//單個數(shù)據(jù)直接定義變量,多個數(shù)據(jù)定義結(jié)構(gòu)體
//{
//	SQDataType a[N];//順序表有10個空間可進行存儲
//	int size;//順序表存了幾個數(shù)據(jù)(有10個空間不一定就存10個數(shù)據(jù))
//}SL;
//這樣結(jié)構(gòu)體類型就可以直接寫成SL

2.2對順序表的增刪查改的接口函數(shù)(以尾插為例)

void SeqListPushBack(struct SeqList *ps, SQDataType x)//尾插
{
	if (ps->size >= N)
	{
		printf("SeqList is full");//防止你尾插太多已經(jīng)大于了順序表最大容量
		return;
	}
	ps->a[ps->size] = x;
	ps->size++;//存儲的數(shù)據(jù)多了一個,size加1個
}

乍一看代碼比較晦澀難懂,我們用圖來理解一下這個代碼:

在這里插入圖片描述

(圖片來自比特就業(yè)課)

圖示順序表有7個空間,我們放了5個數(shù)據(jù),現(xiàn)在要在尾部插入一個數(shù)據(jù),該數(shù)據(jù)下標是5,而ps->size=5(結(jié)構(gòu)體指針相關(guān)知識見筆者結(jié)構(gòu)體文章)所以a[5]也就是a[ps->size]恰好是尾部后一個元素,這里的5改成其他數(shù)也是同樣的道理。

ps->a[ps->size]=x,也就是對尾部后一個元素賦值。

ps->size++是表示順序表存儲的數(shù)據(jù)又多了一個(原本認定順序表存儲5個數(shù)據(jù),你現(xiàn)在添加了一個,認定存儲幾個數(shù)據(jù)也要再加1個)
而你在尾插的過程中,可能插入數(shù)據(jù)多了,甚至多于數(shù)組最大容量,這肯定會有問題,所以我們用了一個if進行判斷一下。

到這里大家可能就會發(fā)現(xiàn)了,在使用靜態(tài)鏈表有兩個不方便的地方:
1.數(shù)組給的空間小了,可能不夠用
2.數(shù)組給的空間大了,可能浪費空間

3動態(tài)順序表

3.1動態(tài)順序表初始化

代碼如下(示例):

typedef int SQDataType;
struct SeqList
{
	SQDataType*a;
	int size;//有效數(shù)據(jù)個數(shù)
	int capacity;//容量
};
//由于沒有數(shù)組a了,所以順序表初始化也要改一下
void SeqListInit(struct SeqList *ps)
{
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

在這里插入圖片描述

(圖片來自比特就業(yè)課)

3.2動態(tài)順序表-尾插

代碼如下(示例):

void SeqListPushBack(struct SeqList *ps, SQDataType x)
{	
	if (ps->size == ps->capacity)//原先空間滿了,無法進行尾插了,需要進行擴容(擴容一般擴2倍)
	{
		int newcapacity = ps->capacity==0?4:ps->capacity*2;//這個4是可以換其他數(shù)的
		//這里是防止原來的容量是0,擴容后的倍數(shù)仍然是0
		SQDataType*tmp = (SQDataType*)realloc(ps->a, newcapacity* sizeof(SQDataType));
		if (tmp == NULL)//防止擴容失敗,也就是沒有剩余空間供它使用了
		{
			printf("realloc is fail\n");
			exit(-1);//退出運行
		}
		else
		{
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
	}
	ps->a[ps->size] = x;
	ps->size++;//存儲的數(shù)據(jù)多了一個,size加1個
}

我們在擴容時,是用一個擴容一個嗎?這樣太浪費時間,一般是擴容所需要的空間的兩倍,realloc函數(shù)可對指針指向的空間進行擴大或縮小,感興趣的同學(xué)自行了解,這里不作深究。

3.3動態(tài)順序表-頭插

了解過尾插,這里講頭插也很容易理解,就是在最前面插入一個內(nèi)容,如何操作呢?把已有的內(nèi)容全部向后移動一位,然后最前面會空出一個空間,然后你放入內(nèi)容
代碼如下(示例):

void SeqListPushFront(struct SeqList *ps, SQDataType x)
{
//原先空間滿了需要進行擴容
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity==0?4:ps->capacity*2;
		//這里是防止原來的容量是0,擴容后的倍數(shù)仍然是0
		SQDataType*tmp = (SQDataType*)realloc(ps->a, newcapacity* sizeof(SQDataType));
		if (tmp == NULL)//防止擴容失敗,也就是沒有剩余空間供它使用了
		{
			printf("realloc is fail\n");
			exit(-1);
		}
		else
		{
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
	}
	int end = ps->size - 1;//確定最后一個內(nèi)容下標
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];//以此把原先的內(nèi)容往后挪一位
		--end;
	}
	ps->a[0] = x;//把需要插入的內(nèi)容放在最開始的空間
	ps->size++;
}

這里需要注意的是,頭插和尾插都面臨一個空間已經(jīng)滿的情況,如果滿了都需要擴容,這個不要忘記。如果你嫌麻煩每次都要寫擴容,你可以寫一個擴容函數(shù),用的時候調(diào)用一下即可。

3.4動態(tài)順序表-尾刪

代碼如下(示例):

void SeqListPopBack(struct SeqList *ps)
{
	assert(ps->size > 0);
	//要進行刪除,首先要有東西可刪
	//這里會進行斷言,如果沒有東西刪會報錯
	ps->size--;
}

這里為什么size- -即可完成尾部數(shù)據(jù)的刪除?解釋是這樣的,size- -后,電腦認為的有效數(shù)據(jù)就少了一個,不管你那個數(shù)據(jù)還在不在,電腦已經(jīng)認為它不再是一個所需的數(shù)據(jù)了,使用順序表時不會對無效數(shù)據(jù)進行考慮。

3.5動態(tài)順序表-頭刪

頭刪也就是把最前面的數(shù)據(jù)刪除,其他數(shù)據(jù)下標依次減1即可
代碼如下(示例):

void SeqListPopFront(struct SeqList *ps)
{
	assert(ps->size > 0);
	int start = 1;
	while (start < ps->size)
	{
		ps->a[start - 1] = ps->a[start];
		++start;
	}
	ps->size--;
}

3.6動態(tài)順序表-任意位置插入數(shù)據(jù)

我們以下面這個順序表舉例

在這里插入圖片描述

我們要在1和2中間插一個數(shù)據(jù)怎么辦?0和1不變,2和3分別向后移
但是考慮到其他的順序表,假設(shè)它原來的數(shù)據(jù)已經(jīng)占滿了所有空間,你再插是不是有可能空間不夠,還有一點,雖說是任意位置插入數(shù)據(jù),你能不能在順序表尾部插入?非法訪問了屬于是??紤]上面幾點,我們有下面的代碼。

void SeqListInsert(struct SeqList *ps, int pos, SQDataType x)
//pos表示插入位置的下標
{
	assert(pos < ps->size);//防止在尾部插入構(gòu)成非法訪問
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

3.7動態(tài)順序表-任意位置刪除數(shù)據(jù)

我們?nèi)砸韵旅娴膱D舉例,要將2刪除怎么辦?把3往前挪一位即可。

在這里插入圖片描述

void SeqListErase(struct SeqList *ps, int pos)
{
	assert(pos < ps->size);
	int start =pos + 1;
	while (start < ps->size)
	{
		ps->a[start - 1] = ps->a[start];
		start++;
	}
	ps->size--;
}

結(jié)束

ps:上述的所有刪除都是刪除數(shù)據(jù),空間是不刪除的。

以上就是C語言編程簡單卻重要的數(shù)據(jù)結(jié)構(gòu)順序表全面講解的詳細內(nèi)容,更多關(guān)于C語言數(shù)據(jù)結(jié)構(gòu)順序表的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • c++中比較好用的“黑科技”

    c++中比較好用的“黑科技”

    這篇文章主要介紹了c++中比較好用的“黑科技”,一些常用小編沒有給大家羅列出,主要給大家介紹了sort函數(shù),需要的朋友可以參考下
    2020-02-02
  • C語言數(shù)據(jù)的存儲專項分析

    C語言數(shù)據(jù)的存儲專項分析

    使用編程語言進行編程時,需要用到各種變量來存儲各種信息。變量保留的是它所存儲的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個變量時,就會在內(nèi)存中保留一些空間。您可能需要存儲各種數(shù)據(jù)類型的信息,操作系統(tǒng)會根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲什么
    2022-07-07
  • C標準庫<assert.h>的實現(xiàn)詳解

    C標準庫<assert.h>的實現(xiàn)詳解

    這篇文章主要介紹了C標準庫<assert.h>的實現(xiàn),主要包括了<assert.h>的基本概念、實現(xiàn)及用法等,需要的朋友可以參考下
    2014-09-09
  • C語言程序設(shè)計第五版譚浩強課后答案(第二章答案)

    C語言程序設(shè)計第五版譚浩強課后答案(第二章答案)

    這篇文章主要介紹了C語言程序設(shè)計第五版譚浩強課后答案(第二章答案),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-04-04
  • 實例講解C++ 命名空間

    實例講解C++ 命名空間

    這篇文章主要介紹了C++ 命名空間的的相關(guān)資料,文中示例代碼非常詳細,供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 如何把C++的源代碼改寫成C代碼的方法

    如何把C++的源代碼改寫成C代碼的方法

    這篇文章主要介紹了如何把C++的源代碼改寫成C代碼,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • 一文帶你了解C語言中static關(guān)鍵字的3個作用

    一文帶你了解C語言中static關(guān)鍵字的3個作用

    static這個關(guān)鍵字是“靜態(tài)”的意思,在C語言里主要有3個作用。這篇文章主要通過一些簡單示例為大家詳細講講這3個左右,感興趣的小伙伴可以了解一下
    2023-04-04
  • 詳解C語言結(jié)構(gòu)體的定義和使用

    詳解C語言結(jié)構(gòu)體的定義和使用

    這篇文章主要為大家介紹了C語言結(jié)構(gòu)體的定義和使用,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C語言計算日期差的方法示例

    C語言計算日期差的方法示例

    這篇文章主要介紹了C語言計算日期差的方法,結(jié)合具體實例形式分析了C語言針對日期轉(zhuǎn)換、運算等相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06
  • 詳解C語言的預(yù)處理效果

    詳解C語言的預(yù)處理效果

    這篇文章主要為大家介紹了C語言的預(yù)處理效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12

最新評論

云林县| 梁平县| 德保县| 开平市| 土默特左旗| 南乐县| 东乌珠穆沁旗| 大庆市| 南召县| 湟中县| 遵义县| 浠水县| 年辖:市辖区| 泸水县| 澄城县| 扶沟县| 德保县| 威信县| 托里县| 渭源县| 巴彦淖尔市| 吉木萨尔县| 屯门区| 汽车| 黄山市| 梁河县| 寿阳县| 九台市| 平凉市| 永福县| 桐城市| 牟定县| 通辽市| 马公市| 三亚市| 盐城市| 阜平县| 民权县| 宁强县| 阜康市| 张家川|