数据结构部分__1、线性表及其操作的实现

先附整体代码,然后讲一下关键部分

#include <iostream>
using namespace std;
#define InitSize 100
typedef  int ElemType;

typedef struct{
    ElemType *data;
    int MaxSize,length;
}SeqList;

void InitList(SeqList &L)//初始化
{
    L.data=new ElemType[InitSize];
    L.length=0;
    L.MaxSize=INT_MAX;
}

int Length(SeqList &L)//表长
{
    return L.length;
}

int LocateList (SeqList &L,int e)//按值输出
{
    
    for(int i=0;i<L.length;i++)
        if(L.data[i]==e) return i+1;
    return 0;
}

int GetElem (SeqList L,int i)//按位输出
{
    return L.data[i-1];
}

bool ListInsert(SeqList &L,int i,ElemType e) //插入
{
    if(i<1||i>L.length+1)
        return false;
    if(L.length>=L.MaxSize)
        return false;
    for(int j=L.length;j>=i;j--)
        L.data[j]=L.data[j-1];
    L.data[i-1]=e;
    L.length++;
    return true;
}

bool ListDelete (SeqList &L,int i,ElemType e)//删除
{
    if(i<1||i>L.length)
        return false;
    if(L.length<L.MaxSize)
        return false;
    for(int j=i;j<L.length;j++)
        L.data[j-1]=L.data[j];
    L.length--;
    return true;
}

void PrintList(SeqList L)//输出
{
    for(int i=0;i<L.length;i++)
        cout<<L.data[i]<<endl;
}

bool Empty(SeqList L)//判空
{
    if(L.length==0) return true;
    return false;
}

void DestroyList(SeqList &L)//销毁操作
{
    L.length=0;
    L.MaxSize=NULL;
    L.data=NULL;
     delete L.data;
}

int main()
{
    SeqList L;
    InitList(L);
    if(Empty(L)) cout<<"Empty"<<endl;
    for(int i=1;i<200;i++)
    {
        ListInsert(L,i,i);
    }
    PrintList(L);
    DestroyList(L);
    PrintList(L);
    if(Empty(L)) cout<<"Empty"<<endl;
    return 0;
}

第一部分、声明

typedef struct{
    ElemType *data;
    int MaxSize,length;
}SeqList;

这个部分主要声明了一个线性表,包括三个部分,一个指针,一个上限,一个有效长度,比较容易理解。

第二部分、初始化

void InitList(SeqList &L)//初始化
{
    L.data=new ElemType[InitSize];
    L.length=0;
    L.MaxSize=INT_MAX;
}

要求有效长度为0,因为线性表内部没有元素。
MaxSize自定义,尽量大一些。
new为分配动态内存,这样即使InitSize少于输入的长度,比如InitSize为100,但是输入199个数据到线性表中都不会溢出,如下所示:

for(int i=1;i<200;i++)
    {
        ListInsert(L,i,i);
    }

第三部分、表长

int Length(SeqList &L)//表长
{
    return L.length;
}

第四部分、按值查找

int LocateList (SeqList &L,int e)//按值输出
{
    
    for(int i=0;i<L.length;i++)
        if(L.data[i]==e) return i+1;
    return 0;
}

遍历线性表,返回特定值的位序,注意不是数组的序号。
第五部分、按位查找

int GetElem (SeqList L,int i)//按位输出
{
    return L.data[i-1];
}

直接输出就行。
第六部分、插入

bool ListInsert(SeqList &L,int i,ElemType e) //插入
{
    if(i<1||i>L.length+1)
        return false;
    if(L.length>=L.MaxSize)
        return false;
    for(int j=L.length;j>=i;j--)
        L.data[j]=L.data[j-1];
    L.data[i-1]=e;
    L.length++;
    return true;
}

这里需要注意的地方很多,
第一点是合法性判断,因为位序从1开始且最后一位可以插入元素,所以是1到length+1。
第二点是长度判断,不允许表的有效长度超过内存上限
第三点是插入,循环部分是针对非尾端插入的情况,即将插入点右端的元素整体右移一个单位,这里要注意,i是位序不是数组序号,起点是有效线性表的的末端,注意这个有效是不包含空的长度,最后一位元素被放到了之前空的位置;大于等于i是因为从右端的第一个元素开始移动,使用位序作为数组序号时,便是指该元素的右端第一个元素。循环中的赋值操作很好理解。
第四点是插入,i-1还是位序和数组序号的区别。
最后有效长度增加要注意。
第七部分、删除

bool ListDelete (SeqList &L,int i,ElemType e)//删除
{
    if(i<1||i>L.length)
        return false;
    if(L.length<L.MaxSize)
        return false;
    for(int j=i;j<L.length;j++)
        L.data[j-1]=L.data[j];
    L.length--;
    return true;
}

如果插入理解了,删除的操作也差不多,这里不做赘述,需要注意循环起点和终点的差异即可,注意有效长度需要减少。
第八部分、输出

void PrintList(SeqList L)//输出
{
    for(int i=0;i<L.length;i++)
        cout<<L.data[i]<<endl;
}

这里直接遍历输出即可,当然也可以用重载“<<”算符的方法,这样输出看着比较简洁。
第九部分、判空

bool Empty(SeqList L)//判空
{
    if(L.length==0) return true;
    return false;
}

如果线性表有效长度为0,即表示表内没有元素了。
第十部分、销毁

void DestroyList(SeqList &L)//销毁操作
{
    L.length=0;
    delete L.data;
    L.MaxSize=NULL;
    L.data=NULL;
}

用glb单步调的时候可以发现声明后的结构体,其data指针是NULL,现在让它恢复到之前的状态即可,length和MaxSize也注意操作,可以再写一个析构函数判断结构体的内存释放,虽然delete代表了一种,但是可以加一些判断语句。

当然上述的函数也可以用友元或者成员函数写,这个看个人喜好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值