1.線性表
1.線性表(linear list)是n個(gè)具有相同特性的數(shù)據(jù)元素的有限序列。 線性表是?種在實(shí)際中廣泛使用的數(shù)據(jù)結(jié)構(gòu),常見(jiàn)的線性表:順序表、鏈表、棧、隊(duì)列、字符串
2.線性表在邏輯上是線性結(jié)構(gòu),也就說(shuō)是連續(xù)的?條直線。但是在物理結(jié)構(gòu)上并不一定是連續(xù)的,線性表在物理上存儲(chǔ)時(shí),通常以數(shù)組和鏈?zhǔn)浇Y(jié)構(gòu)的形式存儲(chǔ)。
案例:蔬菜分為綠葉類、瓜類、菌菇類。線性表指的是具有部分相同特性的一類數(shù)據(jù)結(jié)構(gòu)的集合
2.順序表分類
順序表和數(shù)組的區(qū)別:
順序表的底層結(jié)構(gòu)是數(shù)組,對(duì)數(shù)組的封裝,實(shí)現(xiàn)了常用的增刪改查等接口
2.1 靜態(tài)順序表
靜態(tài)順序表概念:使用定長(zhǎng)數(shù)組存儲(chǔ)元素
缺點(diǎn)是定義空間小了不夠用,定義大了浪費(fèi),不好把控。
2.2 動(dòng)態(tài)順序表
動(dòng)態(tài)順序表概念:使用動(dòng)態(tài)開辟的數(shù)組存儲(chǔ)。
動(dòng)態(tài)順序表 根據(jù)自己的需求調(diào)整大小,
3. 順序表各接口實(shí)現(xiàn)
首先建立3個(gè)文件
1.SeqList.h頭文件,用來(lái)聲明函數(shù)
2.SeqList.c文件,用來(lái)定義函數(shù)
3.Test.c文件,用來(lái)測(cè)試函數(shù)
靜態(tài)順序表只適用于確定知道需要存多少數(shù)據(jù)的場(chǎng)景。靜態(tài)順序表的定長(zhǎng)數(shù)組導(dǎo)致N定大了,空間開多了浪費(fèi),開少了不夠用。所以現(xiàn)實(shí)中基本都是使用動(dòng)態(tài)順序表,根據(jù)需要?jiǎng)討B(tài)的分配空間大小,所以下面我們實(shí)現(xiàn)動(dòng)態(tài)順序表。
1. 定義結(jié)構(gòu)體(Seqlist)
在SeqList.h頭文件中
typedef int SLDataType;
typedef struct Seqlist
{
SLDataType* a;
int size; // 有效數(shù)據(jù)
int capacity; // 空間容量
}SL;
2. 結(jié)構(gòu)體初始化(SLInit)
注意下述代碼皆是:
在SeqList.h頭文件中定義函數(shù)
在SeqList.c文件中實(shí)現(xiàn)函數(shù)
在Test.c文件中測(cè)試函數(shù)
SeqList.h文件中
定義函數(shù):
SeqList.c文件中
實(shí)現(xiàn)函數(shù):
void SLInit(SL *ps) // 數(shù)據(jù)表初始化
{
assert(ps);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
Test.c文件中
測(cè)試函數(shù):
int main()
{
SL s1;
SLInit(&s1);
return 0;
}
調(diào)試結(jié)果:
3.檢查容量 (SLCheckCapacity)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLCheckCapacity(SL* ps) // 檢查內(nèi)存是否足夠,不夠就擴(kuò)容。
{
//一般情況為了避免頻繁插入數(shù)據(jù)而增容,或者一下開辟很大的空間,我們一般是每次增容2倍
assert(ps);
if (ps->size == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity = newCapacity;
}
}
測(cè)試函數(shù):
int main()
{
SL s1;
SLInit(&s1);
SLCheckCapacity(&s1);
return 0;
}
調(diào)試結(jié)果:
4.打印數(shù)據(jù) (SLPrintf)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLPrintf(SL* ps) // 數(shù)據(jù)表打印
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
5.插入操作
5.1 從數(shù)據(jù)頭部插入(SLPushFront)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLPushFront(SL* ps, SLDataType x) // 頭插
{
assert(ps);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;
ps->size++;
}
動(dòng)圖解析:
測(cè)試函數(shù)結(jié)果:
5.2 從數(shù)據(jù)尾部插入(SLPushBack)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLPushBack(SL* ps, SLDataType x) // 尾插
{
assert(ps);
SLCheckCapacity(ps);
ps->a[ps->size++] = x;
}
動(dòng)圖解析:
測(cè)試函數(shù)結(jié)果:
5.3 從任意下標(biāo)位置的插入(SLInsert)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLInsert(SL* ps, int pos, SLDataType x) // 任意下標(biāo)位置的插入
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
動(dòng)圖解析:
測(cè)試函數(shù)結(jié)果:
6.刪除操作
6.1 從數(shù)據(jù)頭部刪除(SLPopFront)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLPopFront(SL* ps) // 頭刪
{
assert(ps);
assert(ps->size>0);
int begin = 1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}
動(dòng)圖解析:
測(cè)試函數(shù)結(jié)果:
6.2 從數(shù)據(jù)尾部刪除(SLPopBack)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLPopBack(SL* ps) // 尾刪
{
assert(ps);
assert(ps->size>0);
ps->size--;
}
動(dòng)圖解析:
測(cè)試函數(shù)結(jié)果:
6.3 從任意下標(biāo)位置的刪除(SLErase)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLErase(SL* ps, int pos) // 任意下標(biāo)位置的刪除
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
// 這里刪除不能用等于ps->size,ps->size看作下標(biāo)的話相當(dāng)于下標(biāo)的最后一個(gè)位置+1
int begin = pos + 1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}
動(dòng)圖解析:
測(cè)試函數(shù)結(jié)果:
7 銷毀操作 (SLDestroy)
定義函數(shù):
實(shí)現(xiàn)函數(shù):
void SLDestroy(SL* ps) // 數(shù)據(jù)表銷毀
{
assert(ps);
if (ps->a != NULL)
{
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
}
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-753966.html
4.完整代碼
4.1 SeqList.h文件
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDataType;
typedef struct Seqlist
{
SLDataType* a;
int size; // 有效數(shù)據(jù)
int capacity; // 空間容量
}SL;
void SLInit(SL *ps); // 數(shù)據(jù)表初始化
void SLDestroy(SL *ps); // 數(shù)據(jù)表銷毀
void SLPushFront(SL* ps, SLDataType x); // 頭插
void SLPushBack(SL *ps ,SLDataType x); // 尾插
void SLPopFront(SL* ps); // 頭刪
void SLPopBack(SL* ps); // 尾刪
void SLCheckCapacity(SL* ps); // 檢查內(nèi)存是否足夠,不夠就擴(kuò)容。
void SLPrintf(SL* ps); // 數(shù)據(jù)表打印
void SLInsert(SL* ps, int pos, SLDataType x); //任意下標(biāo)位置的插入
void SLErase(SL* ps, int pos); //任意下標(biāo)位置的刪除
4.2 SeqList.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void SLCheckCapacity(SL* ps) // 檢查內(nèi)存是否足夠,不夠就擴(kuò)容。
{
assert(ps);
if (ps->size == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity = newCapacity;
}
}
void SLPrintf(SL* ps) // 數(shù)據(jù)表打印
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
void SLInit(SL *ps) // 數(shù)據(jù)表初始化
{
assert(ps);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
void SLDestroy(SL* ps) // 數(shù)據(jù)表銷毀
{
assert(ps);
if (ps->a != NULL)
{
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
}
void SLPushFront(SL* ps, SLDataType x) // 頭插
{
assert(ps);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;
ps->size++;
}
void SLPushBack(SL* ps, SLDataType x) // 尾插
{
assert(ps);
SLCheckCapacity(ps);
ps->a[ps->size++] = x;
}
void SLPopFront(SL* ps) // 頭刪
{
assert(ps);
assert(ps->size > 0);
int begin = 1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}
void SLPopBack(SL* ps) // 尾刪
{
assert(ps);
assert(ps->size>0);
ps->size--;
}
// pos是下標(biāo)
void SLInsert(SL* ps, int pos, SLDataType x) // 任意下標(biāo)位置的插入
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
void SLErase(SL* ps, int pos) // 任意下標(biāo)位置的刪除
{
assert(ps);
assert(pos >= 0 && pos < ps->size); // 這里刪除不能用等于ps->size,ps->size看作下標(biāo)的話相當(dāng)于下標(biāo)的最后一個(gè)位置+1
int begin = pos + 1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}
4.3 Test.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void TestSL1() // 頭插,尾插
{
printf("TestSL1:\n");
SL s1;
SLInit(&s1);
SLPushFront(&s1, 10);
SLPushBack(&s1, 30);
SLPrintf(&s1);
}
void TestSL2() // 頭刪,尾刪
{
printf("TestSL2:\n");
SL s1;
SLInit(&s1);
SLPushFront(&s1, 10);
SLPushBack(&s1, 30);
SLPushFront(&s1, 10);
SLPushBack(&s1, 30);
SLPrintf(&s1);
SLPopBack(&s1);
SLPopFront(&s1);
SLPrintf(&s1);
}
void TestSL3()//任意下標(biāo)位置的插入,刪除測(cè)試
{
printf("TestSL3:\n");
SL s1;
SLInit(&s1);
SLPushFront(&s1, 10);
SLPushBack(&s1, 30);
SLPrintf(&s1);
SLInsert(&s1, 1, 520);
SLPrintf(&s1);
SLErase(&s1, 2);
SLPrintf(&s1);
}
int main()
{
TestSL1();
TestSL2();
TestSL3();
}
運(yùn)行結(jié)果如下:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-753966.html
到了這里,關(guān)于順序表基本操作全面解析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!