顺序表
什么是顺序表
线性表的顺序存储就叫做顺序表
顺序表的结构
#define N 30
#define datatype int
typedef struct {
datatype data[N];
int pos;
}seqlist_t;
顺序表的成员关系
data[0]:线性表的表头,没有前驱,只有后继
data[29]:线性表的尾节点,没有后继,只有前驱
data[n]:data[n-1]就是他的前驱,data[n+1]就是它的后继,最终通过这种方式构成线性表。
顺序表的操作
1.创建顺序表
2.判满
3.插入数据
4.成员的显示
5.判空
6.删除成员
7.根据位置查询数据
8.根据数据查询位置
9.根据位置修改数据
10.根据数据修改数据
11.根据位置插入数据
12.根据位置删除数据
创建顺序表
seqlist_t *SeqListCreate(void)
{
seqlist_t *h;
//创建顺序表
h = (seqlist_t *)malloc(sizeof(*h));
if(h == NULL){
printf("malloc seqlist memory error\n");
return NULL;
}
//设置表中成员的初值
h->pos = -1;
return h;
}
顺序表判满
//判满
int SeqListIsFull(seqlist_t* h)
{
return (h->pos+1) > (N - 1) ? 1 : 0;
}
顺序表插入成员
int SeqListInsert(seqlist_t *h,datatype data)
{
//1.判断顺序表是否是满
if(SeqListIsFull(h)){
printf("seqlist is full\n");
return -1;
}
//2.将数据存放到表中
h->data[++h->pos] = data;
return 0;
}
顺序表成员显示
void SeqListShow(seqlist_t *h)
{
for(int i=0;i<=h->pos;i++){
printf("-%d",h->data[i]);
}
printf("-\n");
}
顺序表判空
// 返回真代表是空,否则就是假
int SeqListIsEmpty(seqlist_t* h)
{
return h->pos == -1 ? 1 : 0;
}
1.1.2顺序表删除最后面的成员
datatype SeqListDelete(seqlist_t* h)
{
if (SeqListIsEmpty(h)) {
printf("seqlist is empty delete error\n");
return (datatype)-1;
}
h->pos--;
return h->data[h->pos + 1];
}
根据位置查询数据
datatype SeqListCheckDataByPos(seqlist_t* h, int pos)
{
// 1.判断pos是否合法
if (pos < 0 || pos > h->pos){
printf("pos input error,please check.\n");
return (datatype)-1;
}
//返回查询到的结果
return h->data[pos];
}
根据数据查询位置
/*
*功能:通过数据查询位置
*参数:
* @h:顺序表的表头指针
* @data:查询的数据
*返回值:成功返回大于等于0的数,失败返回-1
*/
int SeqListCheckPosByData(seqlist_t* h, datatype data)
{
int i;
for(i=0;i<=h->pos;i++){
if(h->data[i] == data){
return i;
}
}
printf("check data not exist\n");
return -1;
}
根据位置修改数据
int SeqListUpdateDataByPos(seqlist_t *h,int pos,datatype ndata)
{
// 1.判断pos是否合法
if (pos < 0 || pos > h->pos){
printf("pos input error,please check.\n");
return -1;
}
//2.更新数据
h->data[pos] = ndata;
return 0;
}
根据数据修改数据
int SeqListUpdateDataByData(seqlist_t *h,datatype odata,datatype ndata)
{
int i;
//查找到元数据,将更新的数据覆盖掉原数据
for(i=0;i<=h->pos;i++){
if(h->data[i] == odata){
h->data[i] = ndata;
return 0;
}
}
printf("update data not exist\n");
return -1;
}
根据位置插入数据
int SeqListInsertByPos(seqlist_t* h, int pos, datatype data)
{
// 1.判满
if (SeqListIsFull(h)) {
printf("seqlist is full,error\n");
return -1;
}
// 2.判断位置是否合法
if (pos < 0 || pos > h->pos + 1) {
printf("insert data by pos,pos error\n");
return -1;
}
// 3.整体向后移动,将新的数据插入
for (int i = h->pos + 1; i > pos; i--) {
h->data[i] = h->data[i - 1];
}
h->data[pos] = data;
// 4.让h->pos++
h->pos++;
// 5.返回值
return 0;
}
根据位置删除数据
int SeqListDeleteByPos(seqlist_t* h, int pos)
{
// 1.判空
if (SeqListIsEmpty(h)) {
printf("seqlist is Empty,error\n");
return -1;
}
// 2.检查位置是否合法
if (pos < 0 || pos > h->pos) {
printf("delete data by pos,pos error\n");
return -1;
}
// 3.pos之后数据整体向前移动
for (int i = pos; i < h->pos; i++) {
h->data[i] = h->data[i + 1];
}
// 4.将h->pos--
h->pos--;
// 5.返回成功
return 0;
}
顺序表的整体的代码
seqlist.h
#ifndef __SEQLIST_H__
#define __SEQLIST_H__
#include <stdio.h>
#include <stdlib.h> // /usr/include
#define N 30
#define datatype int
typedef struct {
datatype data[N];
int pos;
} seqlist_t;
seqlist_t* SeqListCreate(void);
int SeqListIsFull(seqlist_t* h);
int SeqListInsert(seqlist_t* h, datatype data);
void SeqListShow(seqlist_t* h);
int SeqListIsEmpty(seqlist_t* h);
datatype SeqListDelete(seqlist_t* h);
datatype SeqListCheckDataByPos(seqlist_t* h, int pos);
int SeqListCheckPosByData(seqlist_t* h, datatype data);
int SeqListUpdateDataByPos(seqlist_t* h, int pos, datatype ndata);
int SeqListUpdateDataByData(seqlist_t* h, datatype odata, datatype ndata);
int SeqListInsertByPos(seqlist_t* h, int pos, datatype data);
int SeqListDeleteByPos(seqlist_t* h, int pos);
#endif
seqlist.c
#include "seqlist.h"
// #include <seqlist.h> //gcc *.c -I ./
// 问题1:为什么在创建的函数中使用malloc分配内存空间
// 答:如果不使用malloc申请内存,如果定义的是结构体变量,
// 这个结构体变量在栈上存储,当函数被调用的时候分配内存
// 当函数调用结束之后,这个块内存就被释放了,当函数调用结束
// 之后别人就不能使用了。
// 问题2:为什么返回值设计为结构体指针,而不设计为结构体变量?
// 答:如果返回值是结构体变量类型,接收这个返回值的时候也必须
// 定义结构体变量,那么这样的话表在修改后者内存数据的时候,原来
// 的表的数据是不会改变的
seqlist_t* SeqListCreate(void)
{
seqlist_t* h;
// 创建顺序表
h = (seqlist_t*)malloc(sizeof(*h));
if (h == NULL) {
printf("malloc seqlist memory error\n");
return NULL;
}
// 设置表中成员的初值
h->pos = -1;
return h;
}
// 判满
int SeqListIsFull(seqlist_t* h)
{
return (h->pos) == (N - 1) ? 1 : 0;
}
int SeqListInsert(seqlist_t* h, datatype data)
{
// 1.判断顺序表是否是满
if (SeqListIsFull(h)) {
printf("seqlist is full\n");
return -1;
}
// 2.将数据存放到表中
h->data[++h->pos] = data;
return 0;
}
void SeqListShow(seqlist_t* h)
{
for (int i = 0; i <= h->pos; i++) {
printf("-%d", h->data[i]);
}
printf("-\n");
}
// 返回真代表是空,否则就是假
int SeqListIsEmpty(seqlist_t* h)
{
return h->pos == -1 ? 1 : 0;
}
datatype SeqListDelete(seqlist_t* h)
{
if (SeqListIsEmpty(h)) {
printf("seqlist is empty delete error\n");
return (datatype)-1;
}
h->pos--;
return h->data[h->pos + 1];
}
datatype SeqListCheckDataByPos(seqlist_t* h, int pos)
{
// 1.判断pos是否合法
if (pos < 0 || pos > h->pos) {
printf("pos input error,please check.\n");
return (datatype)-1;
}
// 返回查询到的结果
return h->data[pos];
}
/*
*功能:通过数据查询位置
*参数:
* @h:顺序表的表头指针
* @data:查询的数据
*返回值:成功返回大于等于0的数,失败返回-1
*/
int SeqListCheckPosByData(seqlist_t* h, datatype data)
{
int i;
for (i = 0; i <= h->pos; i++) {
if (h->data[i] == data) {
return i;
}
}
printf("check data not exist\n");
return -1;
}
int SeqListUpdateDataByPos(seqlist_t* h, int pos, datatype ndata)
{
// 1.判断pos是否合法
if (pos < 0 || pos > h->pos) {
printf("pos input error,please check.\n");
return -1;
}
// 2.更新数据
h->data[pos] = ndata;
return 0;
}
int SeqListUpdateDataByData(seqlist_t* h, datatype odata, datatype ndata)
{
int i;
for (i = 0; i <= h->pos; i++) {
if (h->data[i] == odata) {
h->data[i] = ndata;
return 0;
}
}
printf("update data not exist\n");
return -1;
}
int SeqListInsertByPos(seqlist_t* h, int pos, datatype data)
{
// 1.判满
if (SeqListIsFull(h)) {
printf("seqlist is full,error\n");
return -1;
}
// 2.判断位置是否合法
if (pos < 0 || pos > h->pos + 1) {
printf("insert data by pos,pos error\n");
return -1;
}
// 3.整体向后移动,将新的数据插入
for (int i = h->pos + 1; i > pos; i--) {
h->data[i] = h->data[i - 1];
}
h->data[pos] = data;
// 4.让h->pos++
h->pos++;
// 5.返回值
return 0;
}
int SeqListDeleteByPos(seqlist_t* h, int pos)
{
// 1.判空
if (SeqListIsEmpty(h)) {
printf("seqlist is Empty,error\n");
return -1;
}
// 2.检查位置是否合法
if (pos < 0 || pos > h->pos) {
printf("delete data by pos,pos error\n");
return -1;
}
// 3.pos之后数据整体向前移动
for (int i = pos; i < h->pos; i++) {
h->data[i] = h->data[i + 1];
}
// 4.将h->pos--
h->pos--;
// 5.返回成功
return 0;
}
main.c
#include "seqlist.h"
int main(int argc, const char* argv[])
{
seqlist_t* h;
// 调用创建线性表的函数
h = SeqListCreate();
if (h == NULL) {
printf("create seqlist error\n");
return -1;
}
// 插入数据
SeqListInsert(h, 10);
SeqListInsert(h, 50);
SeqListInsert(h, 60);
SeqListInsert(h, 100);
// for(int i=0;i<=30;i++){
// SeqListInsert(h, i+1);
// }
// 显示表中的数据
SeqListShow(h);
// 删除成员
// printf("delete :%d\n", SeqListDelete(h));
// printf("delete :%d\n", SeqListDelete(h));
// printf("delete :%d\n", SeqListDelete(h));
// printf("delete :%d\n", SeqListDelete(h));
// printf("delete :%d\n", SeqListDelete(h));
// SeqListShow(h);
// printf("check data = %d\n",SeqListCheckDataByPos(h,2));
// printf("check pos = %d\n",SeqListCheckPosByData(h,101));
// SeqListUpdateDataByPos(h, 2, 1111);
// SeqListShow(h);
// SeqListUpdateDataByData(h, 1111, 2222);
// SeqListShow(h);
// SeqListInsertByPos(h, 2, 123);
// SeqListShow(h);
SeqListDeleteByPos(h,-1);
SeqListShow(h);
return 0;
}
顺序表的优缺点
顺序表的优点:顺序表的结构简单,内存在内存上是连续的,对于顺序表的操作可以通过下标完成。
顺序表的缺点:顺序表的扩展性非常的差,顺序表的位置插入和位置删除的时间复杂度非常的高。