线性表及其实现

线性表的抽象数据类型描述

类项名称:线性表(list)
数据对象集:n个元素的构成的有序序列(n=>0)
操作集:L ∈ List,X ∈ ElementType,整线性表的基本操作主要有:(如下)

/* 线性表的基本操作*/
List MakeEmpty();//初始化一个空的线性表
ElementType FindKth(int K,List L);//返回位序K处的元素
int 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

线性表的顺序存储

注意其实位置
在这里插入图片描述
插入元素时,必须从最后一个元素开始往后移,逐步腾出存放插入元素的空间。若从里至外往后移,即
for(j=i-1;j<=PtrL->Last;j++)
PtrL->Data[j+1] = PtrL->Data[j];
则会导致Data[i-1]到Data[PtrL->Last+1]都是同一个元素,即Data[i-1]。
在这里插入图片描述
顺序存储为利用数组的连续空间顺序存放线性表的各元素, 注意链表元素起始点和末点的下标,还有指针Last指示最后一个元素。

typedef struct LNode*List;
struct LNode{
   ElementType Data[MAXSIZE]; //定义一个数组
   int Last; //代表线性表的最后一个元素
};
struct LNode L;
List PtrL;  //线性表结构的指针

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

线性表顺序存储的主要操作实现 (初始化 查找 插入 删除)

代码如下:

/*初始化*/
List MakeEmpty() 
{  List Ptrl;
  ptrl = (List)malloc(sizeof(struct LNode));//建立空栈表
  PtrL->Last = -1; //  空表,所以last指向-1
  return Ptrl; //返回结构指针
}

/*查找 */
int Find(ElementType X,List PtrL)
{   int i=0;
/*从i=0的位置开始查找,当i<=指针Last所在位置,且指向元素不等于目标X时,i就不断往后移动,也就是i++*/
/*最终肯定会跳出while循环,则进行if-else判断*/
   while(i<=PtrL->Last && PtrL->Data[i]!=X)
       i++;
   if(i>PtrL->Last) return -1; //如果没找到,返回-1
   else return i; //找到后就返回此时的i,即存储位置
} /*平均比较次数为(n+1)/2,平均时间性能为O(n)*/

/*插入第i(1≤i≤n+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->Data[j]; //从最后一个元素开始,将ai~an倒序向后移动
   PtrL->Data[i-1]=X;  //新元素插入
   PtrL->Last++;    //Last仍指向最后元素
   return;
}/*平均移动次数为n/2,平均时间性能为O(n)*/

/*删除第i(1≤i≤n)个元素*/
void Delete(int i,List PtrL)
{   int j;
    if(i<1 || i>PtrL->Last+1){  //检查空表及删除位置的合法性
        printf("不存在第%d个元素",i);
        return;
    }
    for(j=i;j<=PtrL->Last;j++)
        PtrL->Data[j-1] = PtrL->Data[j];  // 将a(i+1)~a(n)顺序向前移动
    PtrL->Last--;    //Last仍指向最后元素 
    return;  
} /*平均移动次数为(n-1)/2,平均时间性能为O(n)*/

线性表的链式存储

不需要逻辑上相邻的两元素物理上也相连,插入、删除时不需要移动数据元素,只需要修改链。
在这里插入图片描述
要在链式存储上插入新元素,首先构造新元素S,再将P的next指针指向S,S的next指针则指向先前P的下一个元素。两个顺序不可调换。

在这里插入图片描述

typedef struct LNode*List;
struct LNode{
    ElementType Data;
    List Next;
};
struct LNode L;
List PtrL;

线性表链式存储的主要操作实现

代码如下:

/*求表长*/
int Length(List PtrL)
{   List p=PtrL; //p指向表的1第一个节点
    int j=0;
    while (p){ 
        p=p->Next; //p不断往后移,直到到最后一个节点,其值为NULL,跳出while循环
        j++; //当前p指向的是第j个节点
    }
    return j;
}

/*查找1:按序号查找:FindKth*/
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:按值查找,Find*/
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)*/
List Insert(ElementType X,int i,List PtrL)
{   List p,s;
    if(i==1){                    //新节点插入在表头
        s=(List)malloc(sizeof(struct LNode));  //申请,填装节点
        s->Data=X;
        s->Next=PtrL;
        return s;
    }
    p=FindKth(i-1,Ptr);   //查找第i-1个节点
    if(P==NULL){   //第i-1个不存在,不能插入
        printf("参数i错");
        return NULL;
     }
     else{
         s=(List)malloc(sizeof(struct LNode));  //申请、填装节点
         s->Data=X;
         s->Next=p->Next;  //新节点插入在第i-1个节点的后面
         p->Next=s;
         return PtrL;
     }
}

/*删除*/
List Delete(int i,List PtrL)
{   List p,s;
    if(i==1){                //若要删除的是表的第一个节点
        s=PtrL;              //s指向第1个节点
        if(PtrL!=NULL)       
            PtrL=PtrL->Next; //从链表中删除
        else return NULL; 
        free(s);             //释放被删除的节点
        return PtrL;
    }
    p=FindKth(i-1,PtrL);
    if(P==NULL){
        printf("第%d个节点不存在",i-1);
        return NULL;}
    else if(p->Next==NULL){
        printf("第%d个节点不存在",i);
        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、付费专栏及课程。

余额充值