数据结构与算法学习笔记二---顺序表的动态分配存储表示和实现(C++)

目录

前言

1.顺序表的动态分配存储表示

2.顺序表的静态存储表示

1.初始化

2.销毁

3.清空

4.判空

5.表长       

6.数据元素

7.获取下标

8.前驱节点

9.后继节点

10.插入

11.删除

12.遍历

13.测试代码


前言

    这篇文章讲的是线性表的动态分配存储表示。

1.顺序表的动态分配存储表示

        在上一篇博客中,我们介绍了线性表的静态分配存储结构。使用静态分配的时候,有个缺点就是数组的长度是固定的,顺序表中数据元素达到上上限之后,我们就无法继续操作了。

         C++中我们除了使用静态数组之外,还可以动态的给数据元素分配存储空间,这样的话线性表的长度就可变了,我们就可以更加灵活的操作表了。

2.顺序表的静态存储表示

       在C++中顺序表的动态分配存储结构定义如下:

//----- 线性表的动态分配顺序存储结构 - - - - -
#define LIST_INIT_SIZE 10  // 线性表存储空间的初始分配量
#define LISTINCREMENT  10   // 线性表存储空间的分配增量
typedef int ElementType;
typedef int Status;
typedef struct {
    ElementType * element; // 存储空间基址
    int length;            // 当前长度
    int lisezsize;         // 当前分配的存储容量(以sizeof(ElementType)为单位)
}SeqList;

        其中,数组指针elem表示线性表的基地址,length表示线性表的当前长度,listsize指示顺序表当前分配的存储空间大小,一旦因为插入元素而空间不足的时候,可进行再分配,即为顺序表增加一个大小存储为LISTINCREMENT个数据元素的空间。

1.初始化

        顺序表的时候分配初始内存空间

// 初始化顺序表
Status initSeqList(SqList *sqList){
    sqList->element = new ElementType[LIST_INIT_SIZE];//分配内存
    if (!sqList->element) {
        return 0; // 内存分配失败
    }
    sqList->length = 0; // 初始长度为0
    sqList->listsize = LIST_INIT_SIZE; // 初始存储容量为初始分配量
    return 1; // 初始化成功
}

2.销毁

        删除动态分配的存储空间,置空指针和容量大小

// 销毁
void destroySqList(SqList *sqList){
    delete [] sqList->element;
    sqList->element = nullptr;//讲指针置空
    sqList->length = 0;
    sqList->listsize = 0;
}

3.清空

        长度置为0

// 清空
void clearSqList(SqList *sqList){
    sqList->length = 0;// 长度置为0.但存储空间不变
}

4.判空

// 判空
Status emptySqList(SqList *sqList){
    return sqList->length == 0;
}

5.表长       

        返回顺序表的长度

// 长度
int staticSqListLength(StaticSqList *sqList){
    return sqList->length;
}

6.数据元素

        遍历数组根据下标获取数据元素

// 获取元素
Status getElemForSqList(SqList *sqList,int location,ElementType * element){
    if (location > sqList->length - 1 || location < 0) {
        return 0;
    }
    *element = sqList->element[location];
    return 1;
}

7.获取下标

// 获取元素下标
Status locationElemForSqList(SqList *sqList,ElementType element,int *location){
    for (int i = 0; i < sqList->length; i++) {
        if (sqList->element[i] == element) {
            * location = i;
            return 1;
        }
    }
    return 0;
}

8.前驱节点

// 前驱节点
Status priorElemForSqList(SqList *sqList,ElementType currentElement,ElementType * priorElement){
    for (int i = 0; i < sqList->length; i++) {
        if (sqList->element[i] == currentElement) {
            if (i >= 1) {
                * priorElement = sqList->element[i-1];
                return 1;
            }
          
        }
    }
    return 0;
}

9.后继节点

// 后继节点
Status nextElemForSqList(SqList *sqList,ElementType currentElement,ElementType * nextElement){
    for (int i = 0; i < sqList->length; i++) {
        if (sqList->element[i] == currentElement) {
            if (i < sqList->length - 1) {
                * nextElement = sqList->element[i+1];
                return 1;
            }
          
        }
    }
    return 0;
}

10.插入

        当我们使用动态分配存储表示顺序表的时候,如果在插入元素时发现顺序表的存储空间已满,我们需要动态地扩展存储空间,以容纳更多的元素。这就涉及到重新分配内存,并将原有数据复制到新的存储空间中,然后再进行元素插入操作。这样可以确保在插入元素时不会受到存储空间的限制。

// 插入
Status insertSqList(SqList *sqList, int pos, ElementType element) {
    if (pos < 0 || pos > sqList->length + 1) {
        return 0;
    }

    // 检查存储空间是否足够,不足则扩展存储空间
    if (sqList->length >= sqList->listsize) {
        ElementType *newElement = new ElementType[sqList->listsize + LISTINCREMENT]; // 新的存储空间
        if (!newElement) {
            return 0; // 内存分配失败
        }
        // 将原有数据复制到新的存储空间中
        for (int i = 0; i < sqList->length; ++i) {
            newElement[i] = sqList->element[i];
        }
        // 释放原有存储空间
        delete[] sqList->element;
        // 更新指针指向新的存储空间
        sqList->element = newElement;
        // 更新存储容量
        sqList->listsize += LISTINCREMENT;
    }

    // 插入位置之后的元素后移
    for (int i = sqList->length; i > pos - 1; i--) {
        sqList->element[i] = sqList->element[i - 1];
    }
    // 插入新元素
    sqList->element[pos - 1] = element;
    // 更新顺序表的长度
    sqList->length++;
    return 1; // 插入成功
}

11.删除

// 删除
Status deleteSqList(SqList *sqList, int i, ElementType *element) {
    if (i < 1 || i > sqList->length || sqList->length == 0) {
        return 0;
    }
    *element = sqList->element[i - 1];
    for (int j = i; j < sqList->length; j++) { // 删除位置之后的元素前移
        sqList->element[j - 1] = sqList->element[j];
    }
    sqList->length--;
    return 1;
}

12.遍历

// 遍历
void traverseSqList(SqList *sqList){
    for (int i = 0; i<sqList->length; i++) {
        cout<<sqList->element[i]<<"\t";
    }
    cout<<endl;
}

13.测试代码

void testSeqList(void){
    SqList sqList;
    cout<<"顺序表初始化......"<<endl;
    if (initSeqList(&sqList)) {
        cout<<"顺序表初始化成功"<<endl;
    }
    cout<<"顺序表判空和长度计算......"<<endl;
    if (emptySqList(&sqList)) {
        cout<<"顺序表为空,长度为"<<SqListLength(&sqList)<<endl;
    }
    cout<<"顺序表插入测试......"<<endl;
    for (int i = 1; i <=11 ; i++) {
        if (insertSqList(&sqList, sqList.length + 1, i)) {
            cout<<"数据元素"<<i<<"插入成功"<<endl;
        }else{
            cout<<"数据元素"<<i<<"插入失败"<<endl;
        }
    }
    cout<<"插入之后的静态顺序表"<<endl;
    traverseSqList(&sqList);
    cout<<"顺序表删除测试......"<<endl;
    ElementType element;
    if (deleteSqList(&sqList, 10, &element)){
        cout<<"数据元素"<<element<<"删除成功"<<endl;
    }
    cout<<"删除之后的静态顺序表"<<endl;
    traverseSqList(&sqList);
    //后继节点测试
    ElementType nextElement;
    if (nextElemForSqList(&sqList, 8, &nextElement)) {
        cout<<"数据元素8"<<"后继节点为:"<<nextElement<<endl;
    }else{
        cout<<"后继节点不存在"<<endl;
    }
    //前驱节点测试
    ElementType priorElement;
    if (priorElemForSqList(&sqList, 8, &priorElement)) {
        cout<<"数据元素8"<<"前驱节点为:"<<priorElement<<endl;
    }else{
        cout<<"前驱节点不存在"<<endl;
    }
    cout<<"顺序表数据元素下标测试......"<<endl;
    for (int i = -1; i <= 12; i++) {
        int location;
        if (locationElemForSqList(&sqList, i, &location)) {
            cout<<"数据元素"<<i<<"下标为:"<<location<<endl;
        }else{
            cout<<"数据元素不存在"<<endl;
        }
    }
    destroySqList(&sqList);
    cout<<"顺序表销毁"<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫柱子哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值