一、概述
1. 概念
数据线性结构按照顺序存储的方式。
2. 优缺点
缺点:①插入和删除操作麻烦。②需要一块很大的连续空间。
优点:查找和替换方便。
3. 操作:
增删改查。
二、代码实现
1. 头文件定义部分
#ifndef __SEQ_H__ //避免头文件被重复包含
#define __SEQ_H__
#include <stdio.h>
#include <stdlib.h>
#define N 10 //数组元素个数
typedef int datatype;
struct seq{ //定义一个顺序表结构体
datatype arr[N]; //数组
int len; //实际数组长度
};
//声明所需要使用的函数
struct seq *seq_init(void) //初始化顺序表
void seq_insert(struct seq* px,datatype data,int loc); //插入
void seq_del(struct seq *px,datatype data); //删除
void seq_replace(struct seq* px,datatype old,datatype new); //修改
void display(struct seq* px); //遍历查询
#endif
2. 函数定义部分
1)顺序表的初始化
#include "seq.h"
/***************************
@brief: 初始化
@para: 无
@retval: 结构体指针
***************************/
struct seq *seq_init(void)
{
/*在堆中申请空间*/
struct seq *p = (struct seq *)malloc(sizeof(struct seq));
if(p == NULL)
{
perror("malloc error");
return NULL;
}
/*设置当前实际数据长度为0*/
p->len = 0;
return p;
}
2)插入部分
#include "seq.h"
/***************************
@brief: 插入
@para: 结构体指针
@para: 要插入的数据
@para: 要插入的位置
@retval: 无
***************************/
void seq_insert(struct seq *px,datatype data, int loc)
{
/*判断位置是否合法*/
if(loc < 0 || loc >px->len) //当插入位置不在表内(超出了表的边界)
{
printf("传入位置不合法\n");
return;
}
/*判断是否存满*/
if(px->len == N)
{
printf("已存满\n");
return;
}
/*移动数据,腾出空位*/
int i;
//因为数组下标是从0开始的,因此最后一个有效元素下标为len-1
for(i = px->len - 1;i>=loc;i--) //从表尾开始遍历,直到要插入的位置
{
px->arr[i+1] = px->arr[i];
}
/*存入数据*/
p->arr[loc] = data;
/*有效数据个数+1*/
px->len++;
}
关于插入部分,我们可以通过画图来促进理解:
假设这个顺序表是商城的水果货柜,现在要把雪梨放在第三个货柜,有一种方法就是把第三个货柜以及之后货柜上的水果整体往后移一个,腾出第三个货柜的位置后把雪梨放进去。
把px->len当做是该商场的柜员,他依次从最后一个柜台开始移动水果,直到到达目标柜台,再把雪梨放进去,这样就完成了插入的操作。
3)删除部分
#include "seq.h"
/***************************
@brief: 删除
@para: 结构体指针
@para: 要删除的数据
@retval: 无
***************************/
void seq_del(struct seq *px,datatype data)
{
int i = 0,j = 0; //i用来遍历,j用来移动
/*遍历整个顺序表*/
while(i<px->len)
{
/*找到要删除的数据位置*/
if(px->arr[i] == data)
{
for(j = i+1;j<=px->len-1;j++)
px->arr[j-1] = px->arr[j];
/*实际数据长度-1*/
px->len--;
continue; //为了删除后续还可能存在的相同数据
}
i++; //往后继续遍历去找符合该数值的数据
}
同样通过画图举例来理解:
假设这个商店的香蕉销量很好已经售罄,因此空出来了一个货柜,为了节省空间,需要把后面货柜的水果往前移。如图:
这个操作需要两个柜员,一个负责寻找的柜员“i”,另一个负责移动的柜员“j”,柜员“i“从第一个货柜开始找香蕉所在的货柜,直到找到香蕉,告诉第二个专门移动水果的柜员“j”,从香蕉货柜的下一个货柜开始往左边移动剩下的水果。
4)替换操作
#include "seq.h"
/***************************
@brief: 修改替换
@para: 结构体指针
@para: 要被替换数据
@para: 要替换数据
@retval: 无
***************************/
void seq_replace(struct seq*px,datatype old,datatype new)
{
/*遍历顺序表*/
int i;
for(i = 0;i < px->len;i++)
{
/*匹配数据*/
if(px->arr[i] == old)
{
/*用新数据覆盖旧数据*/
px->arr[i] = new;
}
}
}
通过画图举例来理解:
还是以商场货柜为例,假设当季的橙子销量不好,商场负责人决定把橙子换成市场销量很好的草莓,则需要一个柜员从头寻找香蕉,然后用草莓把橙子替换下来。
5)遍历展示
#include"seq.h"
/***************************
@brief: 遍历展示
@para: 结构体指针
@para: 要插入的数据
@para: 要插入的位置
@retval: 无
***************************/
void display(struct seq* px)
{
printf("遍历结果:\n");
int i;
for(i = 0 ;i < px->len;i++)
printf("%d ",px->arr[i]);
printf("\n");
}
3.主函数实现部分
该部分实现了通过调用上面的函数来进行顺序表的初始化,增删改查操作,代码如下
#include "seq.h"
int main(void)
{
/*初始化*/
struct seq *px = seq_init();
if(px == NULL)
{
return -1;
}
int loc;
datatype d;
int ret;
printf("开始添加数据\n");
while(1)
{
ret = scanf("%d %d",&d,&loc);
if(ret == 0)
break;
/*插入数据*/
seq_insert(px,d,loc);
display(px); //遍历查询
}
getchar(); //消除回车键
printf("开始删除数据\n");
while(1)
{
ret = scanf("%d",&d);
if(ret == 0)
break;
/*删除数据*/
seq_del(px,d);
display(px);
}
getchar();//消除回车键
printf("开始替换数据\n");
datatype old,new;
while(1)
{
ret = scanf("%d %d",&old,&new);
if(ret == 0)
break;
/*替换数据*/
seq_replace(px,old,new);
display(px);
}
return 0;
}