静态顺序表的基本操作
程序员文章站
2022-06-05 18:22:57
...
静态顺序表,不涉及动态申请空间
一、顺序表概念
1.首先,顺序表的概念了解一下:
顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构。线性表采用顺序存储的方式存储就称之为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
//顺序表声明
typedef int DataType;
#define MAX_SIZE 10
typedef struct SeqList
{
DataType _array[MAX_SIZE];
int _size; // 表示顺序表中有效元素的个数
}SeqList, *PSeqList;
2.特点:
可以通过下标访问,遍历顺序表;但是在顺序表中插入或删除操作比较麻烦(因为需要移大量元素)。
二、顺序表的基本操作
这次的操作对象都是静态顺序表,不涉及动态申请内存
1. 顺序表的初始化:
//SeqList.h
//声明
void SeqListInit(PSeqList ps);
//SeqList.c
//定义
void SeqListInit(PSeqList ps)
{
assert(ps);//顺序表已经定义,若传进来的ps是NULL属非法操作
memset(ps->_array, 0, sizeof(DataType));
ps->_size = 0;
}
2.顺序表尾插操作:
//SeqList.h 声明
void SeqListPushBack(PSeqList ps, DataType data);
//SeqList.c 定义
void SeqListPushBack(PSeqList ps, DataType data)
{
assert(ps);//顺序表已经定义,若传进来的ps是NULL属非法操作
//需要考虑顺序表是否已经满了的情况,如果表已满,无法插入,直接返回
if (MAX_SIZE == ps->_size)
{
printf("顺序表已满!!!\n");
return;
}
else
{
ps->_array[ps->_size] = data;
ps->_size++;//插入成功就让size++;
}
}
3.顺序表的尾删:
//SeqList.h 声明
void SeqListPopBack(PSeqList ps);
//SeqList 定义
void SeqListPopBack(PSeqList ps)
{
assert(ps);//顺序表已经定义,若传进来的ps是NULL属非法操作
//同样,需要判断顺序表是否为空表,若为空,无法删除,直接返回
if (0 == ps->_size)
{
printf("表已空,无法删除!!!\n");
return;
}
else//若顺序表不为空,只需要让size--即可
{
ps->_size--;
}
}
4.顺序表的遍历
为了直观的看出操作是否正确,我们定义了一个辅助函数PrintSeqList,打印顺序表中所有元素。
//SeqList.h 声明
void PrintSeqList(PSeqList ps);
//SeqList.c 定义
void PrintSeqList(PSeqList ps)
{
int i = 0;
assert(ps);顺序表已经定义,若传进来的ps是NULL属非法操作
while (i < ps->_size)
{
printf("%d ", ps->_array[i]);
i++;
}
printf("\n");
}
5.为验证1、2、3、4的操作,我们写了一个测试函数
//test.c
#include "SeqList.h"
//测试函数--测试顺序表的初始化、尾插和尾删操作
void TestSeqListInit_PushBack_PopBack()
{
SeqList seq;//定义顺序表
SeqListInit(&seq);//初始化顺序表
SeqListPushBack(&seq, 0);//对顺序表尾插一个元素
SeqListPushBack(&seq, 1);
SeqListPushBack(&seq, 2);
SeqListPushBack(&seq, 3);
PrintSeqList(&seq);//打印顺序表
SeqListPopBack(&seq);//尾删顺序表的一个元素
PrintSeqList(&seq);
}
//主函数
int main()
{
TestSeqListInit_PushBack_PopBack();//调用测试函数
system("pause");
return 0;
}
测试结果:
6.顺序表的头插
//SeqList.h 声明
void SeqListPushFront(PSeqList ps, DataType data);
//SeqList.c 定义
//顺序表头插相对比较麻烦,需要把第一个及以后元素向后移动
void SeqListPushFront(PSeqList ps, DataType data)
{
int i = 0;
assert(ps);//顺序表已经定义,若传进来的ps是NULL属非法操作
if (MAX_SIZE == ps->_size)
{
//若条件成立,表示表已满,无法插入,直接返回
printf("表已满,无法插入!!!\n");
return;
}
else
{
i = ps->_size;
//把所有元素后移
while (0 != i)
{
ps->_array[i] = ps->_array[i-1];
i--;
}
//将data赋给顺序表第一个元素
ps->_array[0] = data;
ps->_size++;
}
}
7.顺序表的头删
//SeqList.h 声明
void SeqListPopFront(PSeqList ps);
//SeqList.c 定义
//同头插,顺序表的头删也比较麻烦,要搬大量元素
void SeqListPopFront(PSeqList ps)
{
int i = 0;
assert(ps);//参数检验,是否非法
if (0 == ps->_size)
{//表已空,无法删除
printf("表已空!!!\n");
return;
}
else
{//让第二及第二个元素一次向前覆盖即可
while (i < ps->_size-1)
{
ps->_array[i] = ps->_array[i+1];
i++;
}
}
ps->_size--;//最后让用来统计元素个数的size--
}
8.接下来测试顺序表的头插和头删
//test.c
void TestSeqListPushFront_PopFront()
{
SeqList seq;//定义一个顺序表
SeqListInit(&seq);//顺序表初始化
PrintSeqList(&seq);//先打印一遍顺序表,方便对比头插以后结果
SeqListPushFront(&seq, 3);//头插一个元素
SeqListPushFront(&seq, 2);
SeqListPushFront(&seq, 1);
SeqListPushFront(&seq, 0);
PrintSeqList(&seq);//再次打印顺序表
SeqListPopFront(&seq);//头删一个元素
PrintSeqList(&seq);//再次打印顺序表
}
//主函数
int main()
{
TestSeqListPushFront_PopFront();
system("pause");
return 0;
}
测试结果:
9. 在顺序表的pos位置插入元素data
注意:pos位置应该按照数组角度来看,不是客观上的第pos个位置
//SeqList.h 声明
// 顺序表pos位置插入元素data
void SeqListInsert(PSeqList ps, int pos, DataType data);
// SeqList.c 定义
// 顺序表pos位置插入元素data
void SeqListInsert(PSeqList ps, int pos, DataType data)
{
int i = 0;
//参数检验
assert(ps);
if (pos < 0 || pos > MAX_SIZE)
{
printf("pos位置非法!!\n");
return;
}
//要在pos位置插入元素,需要将pos位置及pos以后元素往后移一个单位
//所以需要判断表是否已经满了
if (MAX_SIZE == ps->_size)
{
//表已满,插入失败
printf("表已满,无法插入!!!\n");
return;
}
i = ps->_size - 1;
while (i >= pos)
{
ps->_array[i + 1] = ps->_array[i];
i--;
}
ps->_array[pos] = data;
ps->_size++;
}
10.删除顺序表中pos位置元素
同样注意:pos位置应该按照数组角度来看,不是客观上的第pos个位置
// 删除顺序表pos位置元素
void SeqListErase(PSeqList ps, int pos);
//SeqList.c 定义
// 删除顺序表pos位置元素
void SeqListErase(PSeqList ps, int pos)
{
int i = 0;
//参数检验
assert(ps);
if (pos<0 || pos>MAX_SIZE)
{
printf("pos位置不合法!!!\n");
return;
}
if (0 == ps->_size)
{
printf("表已空!!!\n");
return;
}
//所有参数已检验合格
i = pos;
while (i<ps->_size)
{
ps->_array[i] = ps->_array[i + 1];
i++;
}
ps->_size--;
}
11.测试顺序表的指定位置插入与删除
//测试顺序表指定位置的插入与删除
void TestSeqListInsert_Erase()
{
SeqList seq;//定义顺序表
SeqListInit(&seq); //初始化顺序表
SeqListPushBack(&seq, 0);//给顺序表尾插元素
SeqListPushBack(&seq, 1);
SeqListPushBack(&seq, 3);
PrintSeqList(&seq);//打印顺序表
SeqListInsert(&seq, 2, 2);//在顺序表的第pos+1个位置插入元素2
PrintSeqList(&seq);//打印顺序表
SeqListErase(&seq, 3);//删除顺序表中第pos+1个位置的元素
PrintSeqList(&seq);//打印顺序表
}
//主函数
int main()
{
TestSeqListInsert_Erase();
system("pause");
return 0;
}
测试结果:
12.在顺序表中查找data元素的第一次出现
//SeqList.h 声明
// 在顺序表中查找值为data的元素,找到返回该元素在顺序表中的位置,否则返回-1
int SeqListFind(PSeqList ps, DataType data);
//SeqList.c 定义
// 在顺序表中查找值为data的元素,找到返回该元素在顺序表中的位置,否则返回-1
int SeqListFind(PSeqList ps, DataType data)
{
int i = 0;
//参数检验
assert(ps);
//遍历顺序表,寻找data的第一次出现
while (i < ps->_size)
{
if (ps->_array[i] == data)
{
//data第一次出现,返回它的下标
return i;
}
i++;
}
//顺序表中没有data元素,返回-1
return -1;
}
13.删除顺序表中第一个data元素
//SeqList.h 声明
// 移除顺序表中第一个值为data的元素
void Remove(PSeqList ps, DataType data);
//SeqList.c 定义
// 移除顺序表中第一个值为data的元素
void Remove(PSeqList ps, DataType data)
{
int ret = 0;
//参数检验
assert(ps);
//首先在顺序表中查找data元素,SeqListFind函数是用来在顺序表中查找值为data的元素,找到返回该元素在顺序表中的位置,否则返回-1
//SeqListFind函数的函数声明及定义在12
ret = SeqListFind(ps, data);
if (-1 == ret)
{
//下标为-1,没找到data元素
printf("顺序表中无该元素!!!\n");
return;
}
else
{
//顺序表中有data元素,且第一个data元素下标为ret,调用SeqListErase函数删除下标为ret元素,即删除data元素
//SeqListErase函数在10中定义
SeqListErase(ps, ret);
printf("顺序表中第一个元素为%d的元素已删除\n", data);
}
}
14.删除顺序表中所有值为data的元素
//SeqList.h 声明
// 移除顺序表中所有值为data的元素
void RemoveAll(PSeqList ps, DataType data);
// 移除顺序表中所有值为data的元素
void RemoveAll(PSeqList ps, DataType data)
{
int i = 0;//i当作循环变量,遍历顺序表
int count = 0;//统计在顺序表中删了多少个值data的元素个数
int index = 0;//辅助删除的变量
//参数检验
assert(ps);
while (i < ps->_size)
{
if (data == ps->_array[i])
{
//遇到值为data的元素,跳过,并让计数器+1
i++;
count++;
continue;
}
ps->_array[index] = ps->_array[i];//依次赋值
i++;
index++;
}
//最后让用来统计顺序表中元素个数的size-count,得到现在顺序表中所有元素个数
ps->_size -= count;
printf("顺序表中所有值为%d的元素已删除\n", data);
}
15.测试顺序表的查找函数、删除第一个值为data元素函数以及删除所有值为data的元素
//测试函数 test.c
void TestSeqListRemove_RemoveAll()
{
SeqList seq;//定义顺序表
SeqListInit(&seq);//初始化顺序表
SeqListPushBack(&seq, 0); //给顺序表尾插元素
SeqListPushBack(&seq, 1);
SeqListPushBack(&seq, 2);
SeqListPushBack(&seq, 3);
SeqListPushBack(&seq, 2);
SeqListPushBack(&seq, 2);
SeqListPushBack(&seq, 3);
PrintSeqList(&seq);//打印顺序表
Remove(&seq, 2);//删除顺序表中第一个值为2的元素
PrintSeqList(&seq);//打印顺序表
RemoveAll(&seq, 2);//删除顺序表中所有值为2的元素
PrintSeqList(&seq);//打印顺序表
}
//主函数
int main()
{
TestSeqListRemove_RemoveAll();
system("pause");
return 0;
}
测试结果:
到此几乎顺序表的基本操作就没有了。
本人能力有限,如有错误欢迎指正,谢谢大家!