数据结构 顺序表(动态分配内存)

数据结构 顺序表(动态分配内存)


前言

刚刚写了个静态分配内存的顺序表,再写个动态分配内存的顺序表对比
前一篇文章,静态分配内存的顺序表


一、顺序表

顺序表有两种。一种为静态分配内存,另一种为动态分配内存。本文提供了一种动态分配内存的顺序表的简单实现。参考了数据结构(严蔚敏C语言版)教材。代码仅供参考,学习,
运行环境是Visual Studio 2019
有些判断输入是否合法的说明就跳过了,代码中可能没有体现,读者可以自行补充,

二、代码部分

1.头文件

建立是cpp文件,用c文件也可以,只是需要改变一下读写数据的操作。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
using namespace std;

2.预定义

预先定义一些内容,方便后续操作
这里追求方便,定义了ElemType为int类型,读者可以自己更改为其他类型
其中INITSIZE是初始的顺序表大小
LISTINCREMENT 是每次新增加的大小

#define OK 1 //返回OK,代表操作成功
#define ERROR 0 //返回ERROR,代表操作失败
#define INITSIZE 10
#define LISTINCREMENT 5
typedef int ElemType;  //之后出现的ElemType为int类型,本代码默认数据类型是int

3.定义存储结构

使用结构体定义了存储结构

struct SqList
{
    ElemType* data;  //定义存储空间的基地址
    int length;   //定义顺序表当前长度
    int listsize; //定义顺序表的最大存储容量
};

4.顺序表初始化

初始化需要动态分配内存,使用的c语言的malloc函数,注意malloc的返回值需要强制类型转换。

int InitList(SqList& L)
{
    L.data = (ElemType*)malloc(INITSIZE * sizeof(ElemType));
    if (!L.data)
    {
        cout << "存储空间分配失败" << endl;
        return ERROR;
    }
    L.length = 0;
    L.listsize = INITSIZE;  
    cout << "顺序表已经构建成功" << endl;
    return OK;
}

5.创建顺序表

线性表创建时用到了realloc函数,用于重新分配内存空间
realloc()函数:重新分配空间
参数:原空间基址,现需空间大小
返回值:1. 成功:新空间地址(本质上是一个数值) 2. 失败:NULL
当我们在输入线性表元素个数大于构造空线性表给线性表分配初始容量时,要一直开辟新空间,直到开辟的空间大于需要的空间为止。

int CreateList(SqList& L)
{
    cout << "请输入顺序表中元素的个数" << endl;
    cin >> L.length;
    while (L.length>L.listsize)
    {
        L.data = (ElemType*)realloc(L.data, (L.length + LISTINCREMENT) * sizeof(ElemType));
        L.listsize = L.length + LISTINCREMENT;
    }
    cout << "请输入顺序表中的数据元素,以空格分隔" << endl;
    for (int i = 0; i < L.length; i++)
    {
        cin >> L.data[i];
    }
    return OK;
}

6.遍历顺序表

很简单,不多做说明

int TraverseList(SqList L)
{
    if (L.length == 0)
    {
        cout << "顺序表是空表" << endl;
        return ERROR;
    }
    else
    {
        cout << "该顺序表中的数据元素如下" << endl;
        for (int i = 0; i < L.length; i++)
        {
            if (i == 0)
            {
                cout << L.data[i];
            }
            else
            {
                cout << " " << L.data[i];
            }
        }
        cout << endl;
        return OK;
    }
}

7.销毁顺序表

利用free()函数释放内存空间
并且将L.data指向NULL防止出现野指针

int DistoryList(SqList& L)
{
    if (!L.data)
    {
        cout << "未建立线性表" << endl;
        return ERROR;
    }
    free(L.data);
    L.length = 0;
    L.listsize = 0;
    L.data = NULL; //防止出现野指针
    cout << "线性表已经销毁" << endl;
    return OK;
}

8.重置顺序表

很简单就不多说了

int ClearList(SqList& L) 
{
    if (!L.data)
    {
        cout << "未建立线性表" << endl;
        return ERROR;
    }
    L.length = 0;
    L.listsize = INITSIZE;
    free(L.data);
    L.data = (ElemType*)malloc(INITSIZE * sizeof(ElemType));
    return OK;
}

9.判断顺序表是否为空

也很简单

bool ListEmpty(SqList L)
{
    if (L.length == 0)
    {
        cout << "线性表是空表" << endl;
        return false;
    }
    else
    {
        cout<< "线性表不是空表" << endl;
        return true;
    }
}

10.按位查找顺序表

输入参数为线性表L,查找的位置index 很简单,和静态分配的类似 有需求可以自行重载或者改写函数
int GetElem(SqList L, int index)
{
    if (index < 1 || index > L.length) 
    {
        cout << "请输入正确的元素位序" << endl;
        return ERROR;
    }
    else
    {
        cout << "第" << index << "个位置的元素为:" << L.data[index - 1] << endl;
    }
    return OK;
}

11.按值查找顺序表

输入参数为线性表L,查找的元素e 很简单,和静态分配的类似 有需求可以自行重载或者改写函数
int LocateElem(SqList L, ElemType e)
{
    for (int i = 0; i < L.length; i++)
    {
        if (L.data[i] == e)
        {
            cout << "该元素是该顺序表中的第" << i + 1 << "个元素" << endl;
            return OK;
        }
    }
    return ERROR;
}

12.顺序表某一位置插入元素

注意插入元素后是否会导致超出内存,要判断是否需要进一步动态分布新的内存空间。
其余操作和静态分配类似

int ListInsert(SqList& L, int i, ElemType e)
{
    if (i < 1 || i > L.length + 1)        
    {
        cout << "插入位置不合法" << endl;
        return ERROR;
    }
    if (L.length + 1 > L.listsize)
    {
        L.data = (ElemType*)realloc(L.data, (L.length + LISTINCREMENT) * sizeof(ElemType));
        L.listsize = L.length + LISTINCREMENT;
    }
    for (int j = L.length; j >= i; j--)
    {
        L.data[j] = L.data[j - 1];
    }
    L.data[i - 1] = e;
    L.length++;
    return OK;
}

13.顺序表删除某一位置元素

操作和静态分配类似

int ListDelete(SqList& L, int i)
{
    if (i<1 || i>L.length)
    {
        cout << "删除位置不合法" << endl;
        return ERROR;
    }
    cout << "删除的元素为" << L.data[i - 1] << endl;
    for (int j = i; j < L.length; j++)
    {
        L.data[j - 1] = L.data[j];
    }
    L.length--;
    return OK;
}

14.主函数

测试用的

int main()
{
    SqList L;
    InitList(L);
    CreateList(L);
    TraverseList(L);
    ListInsert(L,1,2);
    TraverseList(L);
    ListDelete(L, 2);
    TraverseList(L);
    return 0;
}

总结

主要是需要注意如何动态分配内存,这里使用了realloc()函数。
整体而言和静态分配内存的顺序表类似

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值