数据结构——线性表之顺序表(C语言)

一。线性表

        线性表 linear list n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串 ...
       线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

二。顺序表

2.1 概念

顺序表是用一段 物理地址连续 的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组 上完成数据的增删查改。
顺序表一般可以分为:
1. 静态顺序表:使用定长数组存储元素
#define N 7

typedef int SLDataType;

typedef struct SList{
    SLDataType array[N];
    size_t size;
}SList;

2. 动态顺序表:使用动态开辟的数组存储
typedef int SLDataType;

typedef struct SList{
    SLDataType *array;
    size_t size;
    size_t capacity;
}SList;

2.2 实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致空间的空余或者不足。所以基本都是使用动态顺序表,根据需要来动态的分配空间大小,下面实现动态顺序表

1.头文件

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* array;
	size_t size;
	size_t capacity; // unsigned int
}SeqList;

// 对数据的管理:增删查改 
void SeqListInit(SeqList* ps,int initCapacity );//初始化
void SeqListDestory(SeqList* ps);//顺序表销毁
void SeqListPrint(SeqList* ps);//打印顺序表
void CheckCapacity(SeqList* ps);//扩容
void SeqListPushBack(SeqList* ps, SLDateType data);//往顺序表尾插一个元素
void SeqListPushFront(SeqList* ps, SLDateType data);//头插
void SeqListPopFront(SeqList* ps);//头删
void SeqListPopBack(SeqList* ps);//删除最后一个元素
int SeqListSize(SeqList* ps);//返回有效元素个数
int SeqListCapacity(SeqList* ps);//获取容量
int SeqListEmpty(SeqList* ps);//检测顺序表是否为空

// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType data);
// 顺序表在pos位置插入data
void SeqListInsert(SeqList* ps, size_t pos, SLDateType data);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, size_t pos);

2.函数功能实现

void SeqListInit(SeqList* ps, SLDateType initCapacity) {  //初始化
    assert(ps);
    initCapacity = initCapacity <= 0 ? 3 : initCapacity;
    ps->array = (SLDateType*)malloc(sizeof(SLDateType) * initCapacity);
    if (NULL == ps->array) {
        assert(0);
        return;
    }
    ps->capacity = initCapacity;
    ps->size = 0;
}
void SeqListDestory(SeqList* ps) {  //顺序表销毁
    assert(ps);
    if (ps->array) {
        free(ps->array);
        ps->array = NULL;
        ps->capacity = 0;
        ps->size = 0;
    }
}
void SeqListPrint(SeqList* ps) {  //打印顺序表
    assert(ps);
    for (int i = 0; i < ps->size; i++) {
        printf("%d ", ps->array[i]);
    }
    printf("\n");
}
void SeqListPushBack(SeqList* ps, SLDateType data) {  //往顺序表尾插一个元素
    assert(ps);

    //扩容
    CheckCapacity(ps);
    ps->array[ps->size] = data;
    ps->size++;
}
void SeqListPushFront(SeqList* ps, SLDateType data) { //头插
    assert(ps);
    //检测空间是否足够
    CheckCapacity(ps);
    for (int pos = ps->size - 1; pos >= 0; pos--) {
        ps->array[pos + 1] = ps->array[pos];
    }
    ps->array[0] = data;
    ps->size++;
}
void SeqListPopFront(SeqList* ps) {  //头删
    assert(ps);
    if (SeqListEmpty(ps)) {
        return;
    }
    for (int pos = 1; pos < ps->size; pos++) {
        ps->array[pos - 1] = ps->array[pos];
    }
    ps->size--;
}
void SeqListPopBack(SeqList* ps) {  //删除最后一个元素
    assert(ps);
    if (SeqListEmpty(ps)) {
        return;
    }
    ps->size--;
}
int SeqListSize(SeqList* ps) {  //返回有效元素个数
    return ps->size;
}
int SeqListCapacity(SeqList* ps) {  //获取容量
    return ps->capacity;
}
int SeqListEmpty(SeqList* ps) {   //检测顺序表是否为空
    return ps->size == 0;
}


void CheckCapacity(SeqList* ps) {
    assert(ps);
    if (ps->size == ps->capacity) {
        int newCapacity = ps->capacity * 2;

        /*int* temp = (int*)malloc(sizeof(int) * newCapacity);
        if (NULL==temp) {
            assert(0);
            return;
        }
        memcpy(temp, ps->array, ps->size * sizeof(int));
        free(ps->array);
        ps->array = temp;
        ps->capacity = newCapacity;*/

        ps->array = (int *)realloc(ps->array, sizeof(int) * newCapacity);
        if (NULL == ps->array) {
            assert(0);
            return;
        }
        ps->capacity = newCapacity;
    }
}
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType data) {
    for (int i = 0; i < ps->size;i++) {
        if (ps->array[i] == data) {
            return 1;
            break;
        }
    }
    return -1;
}
// 顺序表在pos位置插入data
void SeqListInsert(SeqList* ps, size_t pos, SLDateType data) {
    assert(ps);
    if (pos<0||pos>ps->size) {
        printf("pos位置非法!");
        return;
    }
    //检测空间是否足够
    CheckCapacity(ps);
    for (int i=ps->size-1; i>=pos; i--) {
        ps->array[i+1] = ps->array[i];
    }
    ps->array[pos] = data;
    ps->size++;
}

// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, size_t pos) {
    assert(ps);
    if (SeqListEmpty(ps)) {
        return;
    }
    if (pos<0 || pos>=ps->size) {
        printf("pos位置非法!");
        return;
    }
    for (int i=pos+1; i < ps->size; i++) {
        ps->array[i-1] = ps->array[i];
    }
    ps->size--;
}


 

2.3总结

顺序表优点:

1.无需为表示表中元素之间的逻辑关系而增加额外的存储空间

2.存取速度高效,通过下标来直接存储

顺序表缺点:
1.插入删除操作需要移动大量元素


2.当线性表长度变化较大时,难以确定存储空间的容量

(个人见解,还有许多方面)。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值