目錄
1.線性表概念
1.1 什么是順序列表
1.2 線性表
2.順序表實(shí)現(xiàn)
將有以下功能:
詳細(xì)過程
順序表的動(dòng)態(tài)存儲(chǔ)
順序表初始化
尾插
擴(kuò)容
頭插
更改后的尾插
尾刪
頭刪
打印
釋放內(nèi)存
優(yōu)化順序表 (任意位置插入刪除)
優(yōu)化后的頭插尾插
優(yōu)化后的頭刪尾刪
查找和刪除
進(jìn)行裝飾(菜單)
成品
SeqList.h
SeqList.c
Test.c:
1.線性表概念
1.1 什么是順序列表
順序列表(Sequential List)是一種使用連續(xù)的內(nèi)存空間存儲(chǔ)元素的線性數(shù)據(jù)結(jié)構(gòu)。順序列表中的元素按照其在內(nèi)存中的物理順序依次排列,同時(shí)通過索引來訪問元素。
順序列表可以使用數(shù)組來實(shí)現(xiàn),數(shù)組的下標(biāo)就是元素的索引。由于數(shù)組具有隨機(jī)訪問的特性,即可以通過索引直接訪問元素,因此順序列表在查找指定位置的元素時(shí)具有較高的效率。
順序列表的特點(diǎn)包括:
-
連續(xù)的內(nèi)存空間:順序列表中的元素在內(nèi)存中是連續(xù)存儲(chǔ)的,這樣可以通過索引進(jìn)行快速訪問,提高了訪問效率。
-
固定大小:順序列表的大小在創(chuàng)建時(shí)就確定,一旦分配了固定大小的內(nèi)存空間,就無法自動(dòng)擴(kuò)展或縮小。需要預(yù)估元素的個(gè)數(shù),以避免空間浪費(fèi)或溢出。
-
隨機(jī)訪問效率高:由于順序列表基于數(shù)組實(shí)現(xiàn),并支持隨機(jī)訪問,可以在O(1)的時(shí)間復(fù)雜度內(nèi)獲取指定位置的元素值。
-
插入和刪除的效率較低:當(dāng)需要在順序列表的中間位置插入或刪除元素時(shí),需要移動(dòng)部分元素,導(dǎo)致時(shí)間復(fù)雜度為O(n)。因此,在有頻繁的插入和刪除操作時(shí),順序列表的效率可能較低。
需要注意的是,順序列表適用于元素個(gè)數(shù)固定且隨機(jī)訪問較為頻繁的場(chǎng)景。當(dāng)需要頻繁進(jìn)行插入和刪除操作,或者元素個(gè)數(shù)不確定時(shí),可以考慮其他數(shù)據(jù)結(jié)構(gòu),如鏈表。
1.2 線性表
線性表(linear list)是n個(gè)具有相同特性的數(shù)據(jù)元素的有限序列。 線性表是一種在實(shí)際中廣泛使
用的數(shù)據(jù)結(jié)構(gòu),常見的線性表:順序表、鏈表、棧、隊(duì)列、字符串…
線性表在邏輯上是線性結(jié)構(gòu),也就說是連續(xù)的一條直線。但是在物理結(jié)構(gòu)上并不一定是連續(xù)的,
線性表在物理上存儲(chǔ)時(shí),通常以數(shù)組和鏈?zhǔn)浇Y(jié)構(gòu)的形式存儲(chǔ)。
2.順序表實(shí)現(xiàn)
將有以下功能:
// 順序表的動(dòng)態(tài)存儲(chǔ)
typedef struct SeqList
// 基本增刪查改接口
// 順序表初始化
void SeqListInit(SeqList* psl);
// 順序表銷毀
void SeqListDestory(SeqList* psl);
// 順序表打印
void SeqListPrint(SeqList* psl);
// 檢查空間,如果滿了,進(jìn)行增容
void CheckCapacity(SeqList* psl);
// 順序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
// 順序表尾刪
void SeqListPopBack(SeqList* psl);
// 順序表頭插
void SeqListPushFront(SeqList* psl, SLDataType x);
// 順序表頭刪
void SeqListPopFront(SeqList* psl);
// 順序表查找
int SeqListFind(SeqList* psl, SLDataType x);
// 順序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);
// 順序表刪除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);
詳細(xì)過程
定義三個(gè)文件:
頭文件 SeqList.h
函數(shù)的實(shí)現(xiàn)SeqList.c
代碼的測(cè)試 Test.c
順序表的動(dòng)態(tài)存儲(chǔ)
//SeLqist.h
#define N 200
typedef int SLDataType;
//靜態(tài)順序表 -- N太小,可能不夠用 N太大,可能浪費(fèi)空間
//struct SeqList
//{
// SLDataType a[N];
// int size;
// int capa;
//};
//動(dòng)態(tài)順序表
typedef struct SeqList
{
SLDataType* a;// 指向數(shù)組的指針
int size; // 數(shù)據(jù)個(gè)數(shù)
int capacity;// 容量-空間大小
}SL;
順序表初始化
//SeqList.c
void SLInit(SL* ps)
{
ps->a = NULL;
ps->size =ps->capacity= 0;
}
尾插
void SLPushBack(SL* ps, SLDataType x)
{
//檢查容量空間,滿了擴(kuò)容
if (ps->capacity == ps->size)
{
int newCapacity = 0;
if (ps->capacity == 0)
newCapacity = ps->capacity = 4;
else
newCapacity = ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
if (tmp == NULL)
{
printf("realloc fail\n");
//exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[ps->size] = x;
ps->size++;
}
擴(kuò)容
//動(dòng)態(tài)增容
void SLCheckCapacity(SL* ps)
{
//檢查容量空間,滿了擴(kuò)容
if (ps->capacity == ps->size)
{
int newCapacity = 0;
if (ps->capacity == 0)
newCapacity = ps->capacity = 4;
else
newCapacity = ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
if (tmp == NULL)
{
printf("realloc fail\n");
//exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
}
頭插
因?yàn)槎嗵幰M(jìn)行數(shù)據(jù)擴(kuò)容,故將數(shù)據(jù)擴(kuò)容單獨(dú)用寫為一個(gè)函數(shù)
void SLPushBack(SL* ps, SLDataType x)
{
SLCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
更改后的尾插
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
SLCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
尾刪
void SLPopBack(SL* ps)
{
//尾部要?jiǎng)h除的數(shù)字無需重新定義數(shù)字,意義不大
//只需將 size-- 即可(要防止越界)
assert(ps->size>0);//防止空了還繼續(xù)刪除
ps->size--;
}
頭刪
//頭刪
void SLPopFront(SL* ps)
{
assert(ps->size > 0);
int begin = 1;
while (begin<ps->size)
{
ps->a[begin - 1] = ps->a[begin];
++begin;
}
ps->size--;
}
打印
//打印
void SLPrint(SL* ps)
{
assert(ps!=NULL);
for (int i = 0;i < ps->size;i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
釋放內(nèi)存
//釋放內(nèi)存
void SLDestory(SL* ps)
{
assert(ps != NULL);
if (ps->a)
{
free(ps->a);
ps->a = NULL;
ps->capacity = ps->size = 0;
}
}
優(yōu)化順序表 (任意位置插入刪除)
增加順序表功能:在中間部分 插入/刪除 數(shù)字,也可簡(jiǎn)化頭尾插刪代的碼量
//任意位置插入 (插入數(shù)據(jù)都要防止越界)
void SLInsert(SL* ps, int pos, SLDataType x)
{
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)
{
assert(pos >= 0 && pos < ps->size);
int begin = pos;
while (begin<ps->size)
{
ps->a[begin] = ps->a[begin + 1];
++begin;
}
ps->size--;
}
既然已經(jīng)做到在任意位置可以插入代碼,則可以對(duì)之前寫的代碼進(jìn)行簡(jiǎn)化:
優(yōu)化后的頭插尾插
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
SLInsert(ps, ps->size, x);
}
//頭插
void SLPushFront(SL* ps, SLDataType x)
{
SLInsert(ps, 0, x);
}
優(yōu)化后的頭刪尾刪
//尾刪
void SLPopBack(SL* ps)
{
SLErase(ps, ps->size - 1);
}
//頭刪
void SLPopFront(SL* ps)
{
SLErase(ps, 0);
}
查找和刪除
//查找
int SLFind(SL* ps, SLDataType x)
{
for (int i = 0; i <ps->size; i++)
{
if (ps->a[i] == x)
return i;
}
return -1;//沒找到
}
//修改
int SLModify(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
ps->a[pos] = x;
}
測(cè)試該兩項(xiàng)功能test.c:
//
int x = 0;
printf("請(qǐng)輸入你要?jiǎng)h除的值:>");
scanf("%d", &x);
int pos = SLFind(&sl, x);
if (pos != -1)
{
SLErase(&sl, pos);
}
else
printf("沒有找到%d\n",x);
SLPrint(&sl);
//
int y, z;
printf("請(qǐng)輸入你要修改的值和修改后的值:>");
scanf("%d %d", &y,&z);
pos = SLFind(&sl, y);
if (pos != -1)
{
SLModify(&sl, pos,z);
}
else
printf("沒有找到%d\n", y);
SLPrint(&sl);
//
int f = 0;
printf("請(qǐng)輸入你要?jiǎng)h除的值,并刪除所有與之相同的值:>");
scanf("%d", &f);
pos = SLFind(&sl, f);
while (pos!=-1)
{
SLErase(&sl, pos);
pos = SLFind(&sl, f);
}
進(jìn)行裝飾(菜單)
void menu()
{
printf("*******************************\n");
printf("1.頭插 2.尾插 3.查找 \n");
printf("4.刪除 5.連續(xù)刪除 6.修改 \n");
printf("7.打印 8.退出 \n");
printf("*******************************\n");
}
成品
SeqList.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int SLDataType;
//靜態(tài)順序表 -- N太小,可能不夠用 N太大,可能浪費(fèi)空間
//struct SeqList
//{
// SLDataType a[N];
// int size;
// int capa;
//};
//動(dòng)態(tài)順序表
typedef struct SeqList
{
SLDataType* a;// 指向數(shù)組的指針
int size; // 數(shù)據(jù)個(gè)數(shù)
int capacity;// 容量-空間大小
}SL;
//初始化
void SLInit(SL* ps);
//頭插
void SLPushFront(SL* ps, SLDataType x);
//頭刪
void SLPopFront(SL* ps);
//尾插
void SLPushBack(SL* ps, SLDataType x);
//尾刪
void SLPopBack(SL* ps);
//任意位置插入
void SLInsert(SL* ps,int pos, SLDataType x);
//任意位置刪除
void SLErase(SL* ps, int pos);
//打印
void SLPrint(SL* ps);
//動(dòng)態(tài)增容
void SLCheckCapacity(SL* ps);
//釋放內(nèi)存
void SLDestory(SL* ps);
//查找
int SLFind(SL* ps, SLDataType x);
//修改
void SLModify(SL* ps, int pos, SLDataType x);
SeqList.c
#include "SeqList.h"
void SLInit(SL* ps)
{
ps->a = NULL;
ps->size = ps->capacity = 0;
}
//打印
void SLPrint(SL* ps)
{
assert(ps!=NULL);
for (int i = 0;i < ps->size;i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
//動(dòng)態(tài)增容
void SLCheckCapacity(SL* ps)
{
assert(ps != NULL);
//檢查容量空間,滿了擴(kuò)容
if (ps->capacity == ps->size)
{
int newCapacity = 0;
if (ps->capacity == 0)
newCapacity = ps->capacity = 4;
else
newCapacity = ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
if (tmp == NULL)
{
printf("realloc fail\n");
//exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
}
//任意位置插入 (插入數(shù)據(jù)都要防止越界)
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
//挪動(dòng)數(shù)據(jù)
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)
{
assert(pos >= 0 && pos < ps->size);
int begin = pos;
while (begin<ps->size)
{
ps->a[begin] = ps->a[begin + 1];
++begin;
}
ps->size--;
}
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
SLInsert(ps, ps->size, x);
}
//頭插
void SLPushFront(SL* ps, SLDataType x)
{
SLInsert(ps, 0, x);
}
//尾刪
void SLPopBack(SL* ps)
{
SLErase(ps, ps->size - 1);
}
//頭刪
void SLPopFront(SL* ps)
{
SLErase(ps, 0);
}
//查找
int SLFind(SL* ps, SLDataType x)
{
for (int i = 0; i <ps->size; i++)
{
if (ps->a[i] == x)
return i;
}
return -1;//沒找到
}
//修改
void SLModify(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
ps->a[pos] = x;
}
//釋放內(nèi)存
void SLDestory(SL* ps)
{
assert(ps != NULL);
if (ps->a)
{
free(ps->a);
ps->a = NULL;
ps->capacity = ps->size = 0;
}
}
Test.c:
#include "SeqList.h"
void menu()
{
printf("*******************************\n");
printf("1.頭插 2.尾插 3.查找 \n");
printf("4.刪除 5.連續(xù)刪除 6.修改 \n");
printf("7.打印 8.退出 \n");
printf("*******************************\n");
}
int main()
{
//初始化
SL sl;
SLInit(&sl);
int option = -1;
int x,y,z,f;
do
{
menu();
scanf("%d", &option);
int val, pos;
switch (option)
{
case 1:
printf("請(qǐng)輸入要頭插的數(shù)據(jù),以0結(jié)束:>");
scanf("%d", &val);
while (val!=0)
{
SLPushFront(&sl, val);
scanf("%d",&val);
}
break;
case 2:
printf("請(qǐng)輸入要尾插的數(shù)據(jù),以0結(jié)束:>");
scanf("%d", &val);
while (val != 0)
{
SLPushBack(&sl, val);
scanf("%d", &val);
}
break;
case 3:
printf("請(qǐng)輸入要查找的數(shù)字:>");
scanf("%d", &y);
pos = SLFind(&sl, y);
if (pos != -1)
{
printf("找到了%d\n", y);
}
else
printf("沒有找到%d\n", y);
SLPrint(&sl);
break;
case 4:
printf("請(qǐng)輸入你要?jiǎng)h除的值:>");
scanf("%d", &x);
int pos = SLFind(&sl, x);
if (pos != -1)
{
SLErase(&sl, pos);
}
else
printf("沒有找到%d\n", x);
SLPrint(&sl);
break;
case 5:
printf("請(qǐng)輸入你要?jiǎng)h除的值,并刪除所有與之相同的值:>");
scanf("%d", &f);
pos = SLFind(&sl, f);
if (pos != -1)
{
while (pos != -1)
{
SLErase(&sl, pos);
pos = SLFind(&sl, f);
}
}
else
printf("沒有找到要?jiǎng)h除的值%d\n", f);
break;
case 6:
printf("請(qǐng)輸入你要修改的值和修改后的值:>");
scanf("%d %d", &y, &z);
pos = SLFind(&sl, y);
if (pos != -1)
{
SLModify(&sl, pos, z);
}
else
printf("沒有找到%d\n", y);
SLPrint(&sl);
break;
case 7:
SLPrint(&sl);
break;
case 8:
break;
default:
printf("輸入錯(cuò)誤,請(qǐng)重新輸入\n");
break;
}
} while (option!=8);
printf("退出成功\n");
//釋放內(nèi)存
SLDestory(&sl);
return 0;
}
到這里就結(jié)束啦,創(chuàng)作不易,求求點(diǎn)個(gè)贊啦╰(°▽°)╯文章來源:http://www.zghlxwxcb.cn/news/detail-684876.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-684876.html
到了這里,關(guān)于數(shù)據(jù)結(jié)構(gòu):線性表之-順序表的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!