线性表的顺序存储实现和链式存储实现

线性表是由同类型数据元素构成有序序列的线性结构,表中元素个数称为线性表的长度,线性表没有元素的时候称为空表,表起始位置称表头,结束位置称表尾。

线性表有数据对象集和操作集

数据对象集:线性表是n个元素构成的有序序列
操作集:线性表L属于List,整数i表示位置,元素X属于ElementType

线性表基本操作主要有

List MakeEmpty(): 初始化一个空线性表
ElementType FindKth(int K,List L): 在线性表L中查找第K个元素
Find(ElementType X,List L): 在线性表L中查找X的第一次出现
void Insert(ElementType X,int i,List L): 在位序i前插入新元素X
void Delete(int i,List L): 删除指定为序i的元素
int Length(List L):返回线性表L的长度n

同一个问题可以有不同的表现(存储)方法

线性表的顺序存储实现:利用数组的连续存储空间顺序存放线性表的各元素

typedef struct{
    ElementType Data[MAXSIZE]; //定义一个数组,类型为ElementType:想为什么类型都可以
    int Last; //代表线性表的最后一个元素
}List;
List L, *PtrL;

访问下标为i的元素:L.Data[i]或PtrL->Data[i]
线性表的长度:L.Last+1或PtrL->Last+1

主要操作的实现

  • 初始化(建立空的顺序表)
List *MakeEmpty(){
    List *PtrL;
    PtrL = (List)malloc(sizeof(List)); //通过malloc函数为表申请内存空间
    PtrL->Last = -1; //最后一个元素为-1,指该顺序表为空
    return PtrL; //返回值真
}
  • 查找
int Find(ElementType X, List *PtrL){
    int i = 0;
    while(i<=PtrL->Last && PtrL->Data[i] != X){
        i++;
    }
    if(i > PtrL->Last) return -1; //如果没找到,返回-1
    else return i; //找到后返回的是存储位置
}
  • 插入操作实现
/*
    从最后一个元素开始向后移动一个位置,移动了i个元素之后,将要插入的元素插入空缺的位置
    若是从第i-1个元素开始向后移动,从Data[i-1]到Data[PtrL->Last+1]都是同一个值,值为移动之前的Data[i-1]
*/
void Insert(ElementType X,int i,List *PtrL){
    int j;
    if(PtrL->Last == MAXSIZE-1){ //判断表空间是否已满,已满则不能插入
        printf("表满");
        return;
    }
    if(i<1||i>PtrL->Last+2){
        printf("位置不合法");
        return;
    }
    for(j=PtrL->Last;j>=i-1;j--){
        PtrL->Data[j+1] = PtrL(L->Data[j]); //将ai~an倒序向后移动
    }
    PtrL->Data[i-1] = X; //插入新元素
    Ptrl->Last++; //Last仍指向最后元素
    return;
}
  • 删除操作实现
/*
    删除操作和插入操作相反,插入操作是从最后一个元素往后移动直到第i-1个元素
    删除操作是从第i+1个元素开始往前移动直到最后一个元素
*/
void Delete(int i, List *PtrL){
    int j;
    if(i<1||i>PtrL->Last+1){ //检查空表及删除位置的合法性
        printf("不存在第%d个元素",i);
        return;
    }
    for(j=i;i<=PtrL->Last;j++){
        PtrL->Data[j-1] = PtrL->Data[j]; //将ai+1~an的顺序向前移动
    }
    PtrL->Last--; //Last仍然指向最后一个元素
}

线性表的链式存储实现

链表不要求逻辑上相邻的两个元素物理上也相邻,通过”链“建立起数据元素之间的逻辑关系。链表的插入、删除都不需要移动数据元素,只需要修改链。

typedef struct{
    ElementType Data; //每个结点对应的数据
    struct Node *Next; //代表下一个结点的位置
}List;
List L,*PtrL;

主要操作的实现

  • 求表长
int Length(List *PtrL){
    List *p = PtrL; //p指向表的第一个结点
    int j=0;
    while(p){
        p=p->Next;
        j++; //当前p指向的是第j个结点
    }
    return j;
}
  • 查找(1.按序号查找)
List *FindKth(int K,List *PtrL){
    List *p = PtrL;
    int i = 1;
    while(p!=NULL && i<K){
        p=p->Next;
        i++;
    }
    if(i==K) return p; //找到第K个,返回指针
    else return NULL; //否则返回空
}
  • 查找(2.按值查找)
List *Find(ElementType X,List *PtrL){
    List *p = PtrL;
    while(p!=NULL && p->Data != X){
        p = p->Next;
    }
    return p;
}
  • 插入
/*
在第i-1个(1<=i<=n+1)个结点后插入一个值为X的新结点
1.先构造一个新结点,用s指向
2.再找到链表的第i-1个结点,用p指向
3.然后修改指针,插入结点(p之后插入新结点是s)
*/
List *Insert(ElementType X,int i,List *PtrL){
    List *p,*s;
    if(i==1){                               //新结点插入在表头
        s = (List *)malloc(sizeof(List))    //申请、填装结点
        s->Data = X;
        s->Next = Ptrl;
        return s;                           //返回新表头指针
    }
    p = FindKth(i-1,PtrL);                  //查找第i-1个结点
    if(p==NULL){
        printf("参数i错误");
        return NULL;
    }else{
        s = (List *)malloc(sizeof(List));   //申请、填装结点
        s->Data = X;
        //下面两条语句不能够改变顺序,不然值会有错误
        s->Next = p->Next;                  //新结点插入在第i-1个结点的后面
        p->Next = s;
        return PtrL;
    }
}
  • 删除
/*
删除链表的第i(1<=i<=n)个位置上的结点
1.先找到链表的第i-1个结点,用p指向
2.再用指针s指向要被删除的结点(p的下一个结点)
3.然后修改指针,删除s所指结点
4.最后释放s所指结点的空间
*/
List *Delete(int i, List *PtrL){
    List *p, *s;
    if(i==1){                               //若要删除的是表第一个结点
        s = PtrL;                           //s指向第一个结点
        if(PtrL!=NULL) PtrL = PtrL->Next;   //从链表中删除
        else return NULL;                   //如果链表原本就为空,则删除不成功
        free(s);                            //释放被删除的结点
        return PtrL;
    }
    p = FindKth(i-1, PtrL);                 //查找第i-1个结点
    if(p==NULL){
        printf("第%d个结点不存在", i-1);
        return NULL;
    }else if(p->Next == NULL){
        printf("第%d个结点不存在", i-1);
        return NULL;
    }else{
        s = p->Next;                        //s指向第i个结点
        p->Next = s->Next;                  //从链表中删除
        free(s);                            //释放被删除结点
        return PtrL;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值