顺序表中基本操作的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fighting123678/article/details/82695694
//库函数头文件包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

//函数状态码定义
#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE -1
#define OVERFLOW   -2

typedef int  Status;

//顺序表的存储结构定义
#define LIST_INIT_SIZE  100
#define LISTINCREMENT   10
typedef int ElemType;  //假设线性表中的元素均为整型
typedef struct//注意这里的写法
{
    ElemType* elem;   //存储空间基地址
    int length;       //表中元素的个数
    int listsize;     //表容量大小
} SqList;   //顺序表类型定义


一、顺序表的初始化

Status InitList_Sq(SqList &L)
{
    L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));//注意是给L.elem分配空间//在初始化的时候,有长度限制,因为是顺序结构
    if(!L.elem) exit(OVERFLOW); 
    L.length=0;
    L.listsize=LIST_INIT_SIZE;
}

注意:
(1)是给L.elem分配空间,而不是L,不要和链表混淆
(2)在给L.elem分配空间的时候,LIST_INIT_SIZE*sizeof(ElemType),会有具体的长度,因为是顺序结构,有明确的长度,不要和链表混淆,链表才没有具体的长度
(3)在初始化的时候,顺序表长度为0,容量大小为分配空间的大小

算法时间复杂度:O(1)


二、顺序表的创建

Status ListCreate_Sq(SqList &L)
{
    ElemType n,m;
    scanf("%d",&n);
    L.elem=(ElemType*)malloc(n*sizeof(ElemType));//虽然之前已经确定了分配的空间,但是,之后因为有确定的数字了,所以重新分配空间;
    if(!L.elem) exit(OVERFLOW);
    L.length=n;
    L.listsize=n;
    for(int i=0; i<n; i++)
    {
        scanf("%d",&m);
        L.elem[i]=m;//不要忘记这一行;
        //scanf("%d",&L.elem[i]);//这种方法也是对的
    }
    return OK;
}

ListCreate_Sq 和 InitList_Sq是不同的,InitList_Sq是结构初始化,初始化的时候,L.length=0;L.listsize=LIST_INIT_SIZE。ListCreate_Sq 是创建一个顺序表,L.length和L.listsize由输入的值确定。但是两者还是有共同点的,两者都先L.elem=(ElemType*)malloc(....*sizeof(ElemType));
一般是先InitList_Sq(La);然后再CreateList_Sq(La);


三、顺序表的插入

1、指定插入位置

方法1:

Status ListInsert_Sq(SqList &L, int pos, ElemType e)//插入必须要看空间问题,不够的话就重新分配,倒着赋值//注意pos是位置,从1开始的
{
    ElemType* newbase;
    if(pos>=1&&pos<=L.length+1)//pos是位置,别忘记对length+1(length为元素的个数),因为可以插入的位置有n+1个;
    {
        if(L.length>=L.listsize)//这里别忘记等于号,因为等于的话,再插入也会超过内存大小;
        {
            newbase=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));//与LISTINCREMENT相加的是listsize而不是length,因为是增大内存//给newbase动态分配一个长度为LISTINCREMENT的新空间
            if(!newbase) exit(OVERFLOW);//在分配空间方面,都要进行这样的判断;
            L.elem=newbase;//新分配空间的基地址
            L.listsize+=LISTINCREMENT;//重新分配空间了,所以别忘记改变容量的大小。
        }
        for(int i=L.length;i>=pos;i--)
            L.elem[i]=L.elem[i-1];
        L.elem[pos-1]=e;
        L.length++;//多了一个数据元素,所以length也要加一;
        return OK;
    }
    else  return ERROR;//别忘记else
}

L.length++和 return OK总是忘记;
方法2:

Status ListInsert_Sq(SqList &L,int pos,ElemType e)//在pos位置插入e元素
{
    ElemType* newbase;//newbase是ElemType*类型的,别定义错了
    if(pos>=1&&pos<=L.length+1)//可以插入的有n+1个位置,所以,别忘了+1//pos是位置,别忘记对length+1(length为元素的个数),因为可以插入的位置有n+1个;
    {
        if(L.length>=L.listsize)//这里别忘记等于号,因为等于的话,再插入也会超过内存大小;
        {
            newbase=(ElemType*)realloc(L.elem,(LISTINCREMENT+L.listsize)*sizeof(ElemType));//注意是在L.listsize基础上进行的扩充,因为是增大内存,
            if(!newbase) exit(OVERFLOW);//在分配空间方面,都要进行这样的判断;
            L.elem=newbase;
            L.listsize+=LISTINCREMENT;//重新分配空间了,所以别忘记改变容量的大小。
        }
        ElemType *p,*q;
        p=&(L.elem[pos-1]);
        for(q=&(L.elem[L.length-1]);q>=p;q--)
            *(q+1)=*q;
        *p=e;
        L.length++;
        return OK;
    }
    else  return ERROR;//别忘记else
}

注意:
(1)对于在顺序表中插入一个数来说,一定要先判断插入的位置是否是在1—length+1的范围内,在的话,看数据多少是否超过了存储空间的大小,超过了的话,要进行空间重新分配,空间重新分配的时候还不要忘记判断是否分配成功。成功的话,改变内存大小,然后将要插入的位置记录下来,倒着赋值,赋值的时候注意临界点的判断,最后不要忘记长度加一。
(2)newbase到底是什么类型的,自己要分清了
(3)重新分配的时候,是LISTINCREMENT+L.listsize与sizeof相乘
(4)别忘记对于地址的存储

算法的时间复杂度为:O( ListLength(L) )

2、给出一定的条件,插入数据
例如:有序插入函数,L是一个递增的有序顺序表,函数Status ListInsert_SortedSq(SqList &L, ElemType e)用于向顺序表中按递增的顺序插入一个数据。 比如:原数据有:2 5,要插入一个元素3,那么插入后顺序表为2 3 5。 要考虑扩容的问题。

Status ListInsert_SortedSq(SqList &L, ElemType e)
{
    int i=0;
    for(int j=0;j<L.length;j++)
    {
        if(L.elem[j]>e)  break;//注意临界判断条件
        else i++;
    }
    for(int j=L.length; j>=i+1; j--)  L.elem[j]=L.elem[j-1];
    L.elem[i]=e;
    L.length++;//这里不要忘记;
    return OK;
}

注意:

Status ListInsert_SortedSq(SqList &L, ElemType e)
{
    ElemType i=0;
    while(L.elem[i]<e)
    {
        i++;
    }
    for(int j=L.length-1;j>=i;j--)
        L.elem[j+1]=L.elem[j];
    L.elem[i]=e;
    L.length++;//这里不要忘记;
    return OK;
}

这个是错误的,因为,万一想要插入的数比所有的数都打的话,那么i就会无限制地增加

改成

Status ListInsert_SortedSq(SqList &L, ElemType e)
{
    int i=0;
    while(L.elem[i]<e&&i<L.length)//千万不要忘记i<L.length这个条件
    {
        i++;
    }
    for(int j=L.length-1;j>=i;j--)
        L.elem[j+1]=L.elem[j];
    L.elem[i]=e;
    L.length++;//这里不要忘记;
    return OK;
}

注意:增加元素的同时,不要忘记将长度加1;


四、顺序表的删除(删除的时候一定要记得对于位置的判断)
删除pos位置处的元素,并给e赋值为pos位置处的元素
方法1:

Status ListDelete_Sq(SqList &L, int pos, ElemType &e)
{
    if(pos>=1&&pos<=L.length)
    {
        e=L.elem[pos-1];
        for(int i=pos-1;i<=L.length-2;i++)
            L.elem[i]=L.elem[i+1];
        L.length--;
    }
    else  return ERROR;
}

方法2:

Status ListDelete_Sq(SqList &L, int pos, ElemType &e)//删除不用考虑空间问题,一个个前移就好,最后别忘记L.length--
{
    if(pos>=1&&pos<=L.length)
    {
        ElemType *p;
        e=L.elem[pos-1];//先将e赋值,也就是返回删掉了哪个数
        for(p=&(L.elem[pos-1]);p<=&(L.elem[L.length-2]);p++)
            *p=*(p+1);
        L.length--;
    }
    else  return ERROR;
}

注意:
(1)删除元素的同时,不要忘记将长度减1;
(2)删除是正向赋值,插入是倒叙赋值

算法的时间复杂度为:O( ListLength(L) )


五、查询某元素的位置

查询元素e在顺序表的位次并返回

int ListLocate_Sq(SqList L, ElemType e)
{
    int a=-1;
    int i;
    for(i=0; i<L.length; i++)
    {
        if(L.elem[i]==e)
        {
            a=1;
            break;
        }
        else  continue;
    }
    if(a==-1)
    {
        return 0;
    }
    else return i+1;
}

六、对于符合某条件的元素的定位

Status Equal(ElemType a,ElemType b)
{
    if(a==b)  return true;
    else  return false;
}
int LocateElem_Sq(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))//在表中查找第一个值与e满足compare()的元素的位序
{
    ElemType *p;
    int i=1;//i的初值为第1个元素的位序
    p = L.elem; //p的初值为第1个元素的储存位置
    while(i <= L.length && !(* compare)(*p++,e)) i++;
    if(i <= L.length) return i;
    else return 0;
}

/////////////////////////////////用法
if(!LocateElem_Sq(La,elem,Equal))
            ListInsert_Sq(Lc,Lc.length+1,elem);

算法的时间复杂度为:O( ListLength(L) )

猜你喜欢

转载自blog.csdn.net/fighting123678/article/details/82695694