【数据结构】

本文详细介绍了顺序表的概念、结构以及在C语言中的实现,包括创建、判满、插入、显示、判空、删除等基本操作。同时,文章提供了顺序表操作的代码示例,并讨论了顺序表的内存分配原因和返回结构体指针的原因。最后,指出了顺序表的主要优点和缺点,即结构简单但扩展性差,位置操作效率低。
摘要由CSDN通过智能技术生成

顺序表

什么是顺序表

线性表的顺序存储就叫做顺序表

顺序表的结构

#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;
}

顺序表的优缺点

顺序表的优点:顺序表的结构简单,内存在内存上是连续的,对于顺序表的操作可以通过下标完成。

顺序表的缺点:顺序表的扩展性非常的差,顺序表的位置插入和位置删除的时间复杂度非常的高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值