1 概念
线性表:数据和数据之间的一对一的关系
顺序存储:需要在内存中开辟一块连续的空间存储数据,一般使用数组来存储数据,
为了方便对数组进行操作,通常会定义一个变量来保存最后一个元素的下标
2 对顺序表的操作
2.1 创建一个空的顺序表
#include <stdio.h>
#include <stdlib.h>
//对数据的类型进行取别名,方便对表中的数据类型进行修改,
//提高代码的拓展性
typedef int DataType;
//定义一个结构体
typedef struct{
DataType data[32];
int pos;
}seqlist;
//创建一个空的顺序表
seqlist *SeqlistCreate()
{
//在堆区申请空间
seqlist *st = (seqlist *)malloc(sizeof(seqlist));
//初始化,标识当前顺序表中没有元素
st->pos = -1;
//返回顺序表的首地址
return st;
}
2.2 判断顺序表是否为满
//判断顺序表是否为满
//如果为满,函数返回1,否则返回0
int SeqlistIsFull(seqlist *st)
{
#if 0
if(st->pos == N - 1)
{
return 1;
}
else
{
return 0;
}
#endif
return st->pos == N - 1 ? 1 : 0;
}
2.3 插入数据
//插入数据(每调用一次插入一个数据)
void SeqlistInsert(seqlist *st, DataType value)
{
//插入数据之前先判断当前顺序表是否为满
if(SeqlistIsFull(st) == 1)
{
printf("插入失败,顺序表为满\n");
return ;
}
//保存最后一个元素的变量pos自增
st->pos++;
//将数据插入到pos位置的地方
st->data[st->pos] = value;
printf("插入成功\n");
return ;
}
2.4 遍历顺序表
//遍历顺序表
void SeqlistPrint(seqlist *st)
{
int i;
for(i = 0; i <= st->pos; i++)
{
printf("%d ", st->data[i]);
}
putchar(10);
}
2.5 判断顺序表是否为空
//判断顺序表是否为空
//如果为空返回1,失败返回0
int SeqlistIsEmpty(seqlist *st)
{
return st->pos == -1 ? 1 : 0;
}
2.6删除数据并返回删除的数据
//删除数据并返回删除的数据
DataType SeqlistDelete(seqlist *st)
{
//在删除数据之前判断是否为空
if(SeqlistIsEmpty(st) == 1)
{
printf("删除失败,顺序表为空了\n");
return (DataType)-1;
}
DataType value = st->data[st->pos];
st->pos--;
printf("删除成功\n");
return value;
}
2.7 按照位置插入数据
//按照位置插入数据
void SeqlistInserByPos(seqlist *st, int p, DataType value)
{
int i;
//判断顺序表是否为满
if(SeqlistIsFull(st) == 1)
{
printf("插入失败,顺序表为满\n");
return ;
}
//判断插入数据的位置是否合适
if(p < 0 || p > st->pos + 1)
{
printf("插入失败,插入的位置有误\n");
return ;
}
//如果插入数据的位置刚好是原本pos+1,则直接插入即可
if(p == st->pos + 1)
{
st->data[p] = value;
st->pos++;
}
else
{
//将p之后的数据依次向上移动
for(i = st->pos; i >= p; i--)
{
st->data[i+1] = st->data[i];
}
//将插入的数据放在p位置
st->data[p] = value;
st->pos++;
}
printf("按照位置插入成功\n");
}
2.8 按照位置删除数据,返回删除的数据
//按照位置删除数据,返回删除的数据
DataType SeqlistDeleteByPos(seqlist *st, int p)
{
//判断顺序表是否为空
if(SeqlistIsEmpty(st) == 1)
{
printf("删除失败,顺序表为空\n");
return (DataType)-1;
}
//判断删除数据的位置是否合适
if(p < 0 || p > st->pos)
{
printf("删除失败,删除的位置有误\n");
return (DataType)-1;
}
//将要删除的数据保存一下
DataType value = st->data[p];
//将p往上的数据向下移动
int i;
for(i = p; i < st->pos; i++)
{
st->data[i] = st->data[i+1];
}
st->pos--;
printf("按照位置删除数据成功\n");
return value;
}
2.9 按照数据修改数据
//按照数据修改数据
void SeqlistUpdateByData(seqlist *st, DataType OldValue, DataType NewValue)
{
//循环对比每一个数据,如果找到将其改成新的数据
int i;
int flags = 0;
for(i = 0; i <= st->pos; i++)
{
if(st->data[i] == OldValue)
{
st->data[i] = NewValue;
flags = 1;
}
}
if(flags == 0)
{
printf("修改失败,%d不存在\n", OldValue);
}
else
{
printf("按照数据修改数据成功\n");
}
}
2.10 按照位置修改数据
//按照位置修改数据
void SeqlistUpdateByPos(seqlist *st, int p, DataType value)
{
//判断位置是否合适
if(p < 0 || p > st->pos)
{
printf("修改失败,位置有误\n");
return ;
}
st->data[p] = value;
printf("按照位置修改数据成功\n");
}
2.11 按照数据查找位置
//按照数据查找位置
int SeqlistSearchPos(seqlist *st, DataType value)
{
int i;
for(i = 0; i <= st->pos; i++)
{
if(st->data[i] == value)
{
printf("按照数据查找位置成功\n");
return i;
}
}
printf("查找失败,数据%d不存在\n", value);
return -1;
}
2.12 按照位置查找数据
//按照位置查找数据
DataType SeqlistSearchData(seqlist *st, int p)
{
//判断位置是否合适
if(p < 0 || p > st->pos)
{
printf("修改失败,位置有误\n");
return (DataType)-1;
}
printf("按照位置查找数据成功\n");
return st->data[p];
}
3.整体代码
#include <stdio.h>
#include <stdlib.h>
#define N 32
//对数据的类型进行取别名,方便对表中的数据类型进行修改,
//提高代码的拓展性
typedef int DataType;
//定义一个结构体
typedef struct{
DataType data[N];
int pos;
}seqlist;
//创建一个空的顺序表
seqlist *SeqlistCreate();
//判断顺序表是否为满
int SeqlistIsFull(seqlist *st);
//插入数据(每调用一次插入一个数据)
void SeqlistInsert(seqlist *st, DataType value);
//遍历顺序表
void SeqlistPrint(seqlist *st);
//删除数据并返回删除的数据
DataType SeqlistDelete(seqlist *st);
//删除数据并返回删除的数据
DataType SeqlistDelete(seqlist *st);
//按照位置插入数据
void SeqlistInserByPos(seqlist *st, int p, DataType value);
//按照位置删除数据,返回删除的数据
DataType SeqlistDeleteByPos(seqlist *st, int p);
//按照数据修改数据
void SeqlistUpdateByData(seqlist *st, DataType OldValue, DataType NewValue);
//按照位置修改数据
void SeqlistUpdateByPos(seqlist *st, int p, DataType value);
//按照数据查找位置
int SeqlistSearchPos(seqlist *st, DataType value);
//按照位置查找数据
DataType SeqlistSearchData(seqlist *st, int p);
int main(int argc, char const *argv[])
{
seqlist *s1 = SeqlistCreate();
SeqlistInsert(s1, 100);
SeqlistInsert(s1, 200);
SeqlistInsert(s1, 300);
SeqlistInsert(s1, 400);
SeqlistInsert(s1, 500);
SeqlistInsert(s1, 600);
SeqlistPrint(s1);
DataType del_val;
del_val = SeqlistDelete(s1);
printf("删除的元素是%d\n", del_val);
SeqlistPrint(s1);
SeqlistInserByPos(s1, 2, 888);
SeqlistPrint(s1);
DataType del_val1;
del_val1 = SeqlistDeleteByPos(s1, 2);
printf("第2个位置删除的元素是%d\n", del_val1);
SeqlistPrint(s1);
SeqlistUpdateByData(s1, 300, 999);
SeqlistPrint(s1);
SeqlistUpdateByPos(s1, 2, 300);
SeqlistPrint(s1);
int p;
p = SeqlistSearchPos(s1, 300);
printf("数据300的位置是%d\n", p);
DataType data1;
data1 = SeqlistSearchData(s1, 2);
printf("位置2的数据是%d\n", data1);
return 0;
}
//需要将每一个功能封装成函数,这样调用起来更加方便
//创建一个空的顺序表
seqlist *SeqlistCreate()
{
//在堆区申请空间
seqlist *st = (seqlist *)malloc(sizeof(seqlist));
//初始化,标识当前顺序表中没有元素
st->pos = -1;
printf("顺序表创建成功\n");
//返回顺序表的首地址
return st;
}
//判断顺序表是否为满
//如果为满,函数返回1,否则返回0
int SeqlistIsFull(seqlist *st)
{
#if 0
if(st->pos == N - 1)
{
return 1;
}
else
{
return 0;
}
#endif
return st->pos == N - 1 ? 1 : 0;
}
//插入数据(每调用一次插入一个数据)
void SeqlistInsert(seqlist *st, DataType value)
{
//插入数据之前先判断当前顺序表是否为满
if(SeqlistIsFull(st) == 1)
{
printf("插入失败,顺序表为满\n");
return ;
}
//保存最后一个元素的变量pos自增
st->pos++;
//将数据插入到pos位置的地方
st->data[st->pos] = value;
printf("插入成功\n");
return ;
}
//遍历顺序表
void SeqlistPrint(seqlist *st)
{
int i;
for(i = 0; i <= st->pos; i++)
{
printf("%d ", st->data[i]);
}
putchar(10);
printf("顺序表遍历成功\n\n");
}
//判断顺序表是否为空
//如果为空返回1,失败返回0
int SeqlistIsEmpty(seqlist *st)
{
return st->pos == -1 ? 1 : 0;
}
//删除数据并返回删除的数据
DataType SeqlistDelete(seqlist *st)
{
//在删除数据之前判断是否为空
if(SeqlistIsEmpty(st) == 1)
{
printf("删除失败,顺序表为空了\n");
return (DataType)-1;
}
DataType value = st->data[st->pos];
st->pos--;
printf("删除成功\n");
return value;
}
//按照位置插入数据
void SeqlistInserByPos(seqlist *st, int p, DataType value)
{
int i;
//判断顺序表是否为满
if(SeqlistIsFull(st) == 1)
{
printf("插入失败,顺序表为满\n");
return ;
}
//判断插入数据的位置是否合适
if(p < 0 || p > st->pos + 1)
{
printf("插入失败,插入的位置有误\n");
return ;
}
//如果插入数据的位置刚好是原本pos+1,则直接插入即可
if(p == st->pos + 1)
{
st->data[p] = value;
st->pos++;
}
else
{
//将p之后的数据依次向上移动
for(i = st->pos; i >= p; i--)
{
st->data[i+1] = st->data[i];
}
//将插入的数据放在p位置
st->data[p] = value;
st->pos++;
}
printf("按照位置插入成功\n");
}
//按照位置删除数据,返回删除的数据
DataType SeqlistDeleteByPos(seqlist *st, int p)
{
//判断顺序表是否为空
if(SeqlistIsEmpty(st) == 1)
{
printf("删除失败,顺序表为空\n");
return (DataType)-1;
}
//判断删除数据的位置是否合适
if(p < 0 || p > st->pos)
{
printf("删除失败,删除的位置有误\n");
return (DataType)-1;
}
//将要删除的数据保存一下
DataType value = st->data[p];
//将p往上的数据向下移动
int i;
for(i = p; i < st->pos; i++)
{
st->data[i] = st->data[i+1];
}
st->pos--;
printf("按照位置删除数据成功\n");
return value;
}
//按照数据修改数据
void SeqlistUpdateByData(seqlist *st, DataType OldValue, DataType NewValue)
{
//循环对比每一个数据,如果找到将其改成新的数据
int i;
int flags = 0;
for(i = 0; i <= st->pos; i++)
{
if(st->data[i] == OldValue)
{
st->data[i] = NewValue;
flags = 1;
}
}
if(flags == 0)
{
printf("修改失败,%d不存在\n", OldValue);
}
else
{
printf("按照数据修改数据成功\n");
}
}
//按照位置修改数据
void SeqlistUpdateByPos(seqlist *st, int p, DataType value)
{
//判断位置是否合适
if(p < 0 || p > st->pos)
{
printf("修改失败,位置有误\n");
return ;
}
st->data[p] = value;
printf("按照位置修改数据成功\n");
}
//按照数据查找位置
int SeqlistSearchPos(seqlist *st, DataType value)
{
int i;
for(i = 0; i <= st->pos; i++)
{
if(st->data[i] == value)
{
printf("按照数据查找位置成功\n");
return i;
}
}
printf("查找失败,数据%d不存在\n", value);
return -1;
}
//按照位置查找数据
DataType SeqlistSearchData(seqlist *st, int p)
{
//判断位置是否合适
if(p < 0 || p > st->pos)
{
printf("修改失败,位置有误\n");
return (DataType)-1;
}
printf("按照位置查找数据成功\n");
return st->data[p];
}
4.扩展用法
1、删除重复数据(将先出现的数据与后面的数据对比,如果有重复的将后面的数据删除)
s1:1 2 2 1 1 3 4 3 2 4 5 3 4 5 4 1
......
s1:1 2 3 4 5
void SeqlistDeleteRepaet(seqlist *st)
{
int i, j;
for(i = 0; i < st->pos; i++)
{
//将i位置的数据与后面每一个位置的数据进行对比
for(j = i + 1; j <= st->pos; j++)
{
//如果值一样,将后面j位置的数据删除
if(st->data[i] == st->data[j])
{
//按照j位置删除数据
SeqlistDeleteByPos(st, j);
//j--的目的是为了防止删除位置的数据不做比较
j--;
}
}
}
}
2、合并表(将s2里面与s1不一样的数据保存在s1的后面)
s1:1 2 3 4 5
s2:1 3 5 7 9
......
s1:1 2 3 4 5 7 9
void SeqlistUnion(seqlist *s1, seqlist *s2)
{
//循环拿去每一个s2的数据与s1的数据进行对比
int i;
for(i = 0; i <= s2->pos; i++)
{
//调用按照数据查找位置函数,将s2的数据在s1中找位置
//如果返回值等于-1,说明s1中没有s2这个数据
if(SeqlistSearchPos(s1, s2->data[i]) == -1)
{
SeqlistInsert(s1, s2->data[i]);
}
}
}