顺序表的实现

175 阅读3分钟

顺序表的实现

这里主要以动态分配内存为案例来实现一个顺序表。

1、结构体定义

typedef int SLDataType;
​
typedef struct SeqList
{
    SLDataType * a;    // 指针
    int size;          // 顺序里面元素个数
    int capacity;      // 顺序表容量
}SeqList;
​

2、具体实现

初始化

void SeqListInit(SeqList* pq)
{
    assert(pq);
    pq->a = NULL;//初始化指针,该指针是malloc开辟连续内存的首地址
    pq->size = pq->capacity = 0;
}
​

销毁

void SeqListDestroy(SeqList* pq)
{
    assert(pq);
    free(pq->a);
    pq->a = NULL;
    pq->capacity = pq->size = 0;
​
}
​

顺序表的打印

void SeqListPrint(SeqList* pq)
{
    assert(pq);
​
    for (int i = 0; i < pq->size; i++)
    {
        printf("%d ", pq->a[i]);
    }
    printf("\n");
​
}
​

动态数组扩容

void CapacityCheck(SeqList* pq)
{
    assert(pq);
​
    // 判断是否存满
    if (pq->size == pq->capacity)
    {
        // 还需要判断一下是否是空的,因为后面是要在capacity的基础上扩容(capacity的2倍,如果capacity=0,那么会出问题)
        int newcapacity = pq->capacity = 0 ? 4 : pq->capacity * 2;
​
        SLDataType* tmp = (SLDataType*)realloc(pq->a, sizeof(SLDataType) * newcapacity);
        if (tmp == NULL)
        {
            printf("realloc fail\n");
            exit(-1);
        }
        else
        {
            // 有可能当前内存不够扩容,因此在另一块内存上开辟,所以起始地址会变换
            pq->a = tmp;
            pq->capacity = newcapacity;
        }
    }
}
​

尾插插入元素

void SeqListPushBack(SeqList* pq, SLDataType x)
{
    assert(pq);
​
    // 首先要检查顺序表容量是否充足,如果容量不充足需要扩容
    CapacityCheck(pq);
​
    // 尾插
    pq->a[pq->size] = x;
    pq->size++;
}
​

头部插入元素

void SeqListPushFront(SeqList* pq, SLDataType x)
{
    assert(pq);
​
    // 首先检查顺序表容量是否充足,如果容量不充足需要扩容
    CapacityCheck(pq);
​
    // 头插
    for (int i = pq->size - 1; i >= 0; i--)
    {
        pq->a[i + 1] = pq->a[i];
    }
​
    pq->a[0] = x;
    pq->size++;
}

头插的时候需要将顺序表中的元素,从最后一个开始往后挪动,把第一个位置空下来然后将元素插入进去。

尾删和头删

void SeqListPopBack(SeqList* pq)
{
    assert(pq);
    assert(pq->size > 0); // 顺序表中没有数据就不能尾删
    
    pq->size--;
}
​
void SeqListPopFront(SeqList* pq)
{
    assert(pq);
    assert(pq->size > 0); // 顺序表中没有数据就不能头删
​
    for (int i = 0; i < pq->size - 1; i++)
    {
        pq->a[i] = pq->a[i + 1];
    }
​
    pq->size--;
    
}

尾删的时候,我们只需要将最后一个元素的位置当作空就行;头删的时候,需要将第二个元素到最后一个元素往前挪动。

按值查找

int SeqListFind(SeqList* pq, SLDataType x)
{
    assert(pq);
​
    for (int i = 0; i < pq->size; i++)
    {
        if (pq->a[i] == x)
            return i;
    }
​
    return -1;
}
​

在任意位置插入元素

void SeqListInsert(SeqList* pq, int pos, SLDataType x)
{
    assert(pq);
    assert(pos >= 0 && pos <= pq->size); // 需要确保要插入的位置在[0,pq->size]范围内,pq->size位置插入相当于尾插
​
    for (int i = pq->size - 1; i >= pos; i--)
    {
        pq->a[i + 1] = pq->a[i];
    }
​
    pq->a[pos] = x;
    pq->size++;
}
​

删除任意位置的元素

void SeqListErase(SeqList* pq, int pos)
{
    assert(pq);
    assert(pos >= 0 && pos <= pq->size - 1); // 需要保证要删除的元素位置是已有元素的位置
​
    for (int i = pos; i < pq->size - 1; i++)
    {
        pq->a[i] = pq->a[i + 1];
    }
    pq->size--;
}
​

修改元素

void SeqListModify(SeqList* pq, int pos, SLDataType x)
{
    assert(pq);
    assert(pos >= 0 && pos <= pq->size - 1); // 需要保证要修改的元素位置是已有元素的位置
​
    pq->a[pos] = x;
}

3、最终实现

image-20220812210359258.png