数据结构——动态顺序表

  1. 顺序表的基础结构

顺序表在创建时,我们需要知道,在顺序表中我们要插入数据,在插入数据之后有当前的有效空间,因此我们便能得到顺序表的结构如下

typedef int SLDateType;//这里使用typedef是因为我们不知道以后插入的数据是什么类型,
//若是要对插入的数据类型作出修改时,只需要在此修改即可

typedef struct SeqList
{
    SLDateType* a;//定义一个插入数据类型的数组
    int size;//决定插入数据后的有效空间
    int capacity;//定义一个有效空间的上限
}SeqList;
  1. 顺序表的数据操作

对顺序表进行实际操作应使用指针,不然函数之中改变的只是形参。

①顺序表的初始化

#define CAPACI_MAX 1000//用宏定义方便修改有效空间最大容量

void SeqListInit(SeqList* ps)
{
    assert(ps);

    //使用malloc将a置为动态数组
    ps->a = (SLDateType*)malloc(sizeof(SLDateType)*CAPACI_MAX);
    if (NULL == ps->a)
    {
        printf("malloc fail");
        return;
    }

    ps->size = 0;
    ps->capacity = CAPACI_MAX;
}

②顺序表的空间释放

void SeqListDestroy(SeqList* ps)
{
    assert(ps);

    free(ps->a);
    ps->a = NULL;
    ps->size = 0;
    ps->capacity = 0;
}

③顺序表的数值打印

void SeqListPrint(SeqList* ps)
{
    assert(ps);

    int i = 0;
    for (i = 0; i < (ps->size); i++)
    {
        printf("%d ", ps->a[i]);
    }
    printf("\n");
}

④顺序表的头部数值插入

void SeqListPushFront(SeqList* ps, SLDateType x)
{
    assert(ps);

    SeqListCapCheck(ps);//在插入数据前需要判断当前有效空间是否已经到了上限,
    //如果到了需要进行扩容操作

    int end = ps->size;
    while (end != 0)
    {
        ps->a[end] = ps->a[end - 1];
        end--;
    }
    ps->a[end] = x;
    ps->size++;
}

⑤顺序表的头部数值删除

void SeqListPopFront(SeqList* ps)
{
    assert(ps);

    int tail = 0;
    while (tail != ps->size)
    {
        ps->a[tail] = ps->a[tail + 1];
        tail++;
    }

    ps->a[tail] = 0;
    ps->size--;
}

⑥顺序表的尾部数值插入

void SeqListPushBack(SeqList* ps, SLDateType x)
{
    assert(ps);

    SeqListCapCheck(ps);

    ps->a[ps->size] = x;
    (ps->size)++;
}

⑦顺序表的尾部数值删除

void SeqListPopBack(SeqList* ps)
{
    assert(ps);

    ps->a[ps->size-1] = 0;
    ps->size--;
}

⑧顺序表的指定数值查找

int SeqListFind(SeqList* ps, SLDateType x)
{
    assert(ps);

    int i = 0;
    for (i = 0; i < (ps->size); i++)
    {
        if (ps->a[i] == x)
        {
            return i;
        }
    }

    return -1;
}

⑨顺序表的指定位置数值插入

void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
    assert(ps);
    assert(pos >= 0 && pos <= ps->size);

    SeqListCapCheck(ps);

    int end = ps->size;
    while (end != pos)
    {
        ps->a[end] = ps->a[end - 1];
        end--;
    }

    ps->a[end] = x;
    ps->size++;
}

⑩顺序表的指定位置数值删除

void SeqListErase(SeqList* ps, int pos)
{
    assert(ps);
    assert(pos >= 0 && pos <= ps->size);

    ps->a[pos] = 0;

    int end = ps->size - 1;
    while (pos != end)
    {
        ps->a[pos] = ps->a[pos + 1];
        pos++;
    }

    ps->size--;
    ps->a[ps->size] = 0;
}

⑪顺序表的内存检测是否足够

void SeqListCapCheck(SeqList* ps)
{
    assert(ps);

    if (ps->size == ps->capacity)
    {
        SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType) * (ps->capacity) * 2); 
        if (NULL == tmp)
        {
            printf("realloc fail");
            return;
        }
        ps->a = tmp;
        ps->capacity *= 2;
    }
}

3.顺序表的优势与劣势

①优势:

⑴随机访问:由于顺序表中的元素在内存中是连续存储的,因此可以通过元素的下标值(索引)来直接访问和操作元素,这样可以实现O(1)的随机访问效率。

⑵缓存友好:顺序表的存储结构使得它更容易被计算机的缓存系统所利用,这样可以提高访问速度。

⑶内存占用:由于顺序表使用一段连续的存储空间来存储元素,因此相比链式数据结构,顺序表更加紧凑,占用的内存空间更小。

②劣势:

⑴插入和删除:在顺序表中插入和删除元素时,需要将插入或删除点后的所有元素向后或向前移动,这样会导致操作的时间复杂度为O(n),其中n是表中元素的个数。

⑵动态扩容:当顺序表的存储空间不足时,需要进行动态扩容。这涉及到重新分配一段更大的内存空间,并将原来的元素复制到新的内存空间中。这样会导致操作的时间复杂度为O(n),其中n是表中元素的个数。

⑶内存浪费:由于有些顺序表是静态的,即其大小在创建时已经确定,因此如果表中元素的数量不够多,就会导致内存的浪费。同时,如果元素的数量超过了顺序表的大小,就需要进行动态扩容,这也会导致一定的内存浪费。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值