线性表(链表)

2.1链表的定义和表示

存储特点:用一组任意的储存单元存储线性表的数据元素(存储单元可以是连续的,也可以是不连续的)。

对于数据元素来说,需要存储本身信息和一个指示其直接后继的信息(后面的存储位置)。

这两部分信息组成数据的存储影像,称为结点。

两个域:数据域和指针域。

指针域中的储存信息为指针或链,n个结点的储存影像链接成一个链表,若每个结点只包含一个指针域称单链表,若含有两个指针域,则称其为双链表。

单链表的储存结构:

typedef struct LNode
{
    ElemType data;
    struct LNode *next;//指针域
}LNode,*LinkList;//两个变量名强调的重点不同

双链表的储存结构:

//双向链表
typedef struct DuLNode//这个因为有两个指针,需重新定义
{
    ElemType data;//数据域
    struct DuLNode *prior;
    struct DuLNode *next;
}DuLNode,*DuLinkList;

2.2单链表基本操作的实现

1)初始化

构造一个空链表

//初始化(构造一个空的链表)
Status InitList(LinkList &L)//Status为函数类型(当return值为函数结果状态时用)
{
    L=new LNode;
    l->=NULL;
    return OK;
}

2)取值

和顺序表不同的,储存单元并没有相邻,而是根据下个链域来依次访问。

//取值
Status GetElem(LinkList &L,int i,ElemType &e)//获取第i个数据元素的值
{

    p=L->next;
    int n=1;//这的取值与获取元素的位置有关;不是0
    while(p!=NULL  && n<i)
    {
        p=p->next;
        n=n+1;
    }
    if(n>i && p==NULL)
        return ERROR;//其实我感觉不太需要这步;
    e=p->data;
    return OK;
}

3)查找

跟顺序表中特别类似依次与元素值比较来进行寻找。

//查找
Status *LocateElem(LinkList L,ElemType e)//这个是根据值查找,elemtype代表所有可能的数据类型,
{
    p=L->next;
    n=1;
    while(!p && p->data!=e)
    {
        p=p->next;
        n=n+1;//这个有点多余,另一种方法,比较麻烦;
    }
    return p;//这里也可以返回n,根据取值也可以找到
}

4)插入

单链表的插入

根据位置进行插入,插入第i个位置,首先找到第i-1个结点,根据第i-1结点来进行插入。

//插入
Status ListInsert(LinkList &L,int i,ElemType e)//这是根据位置插入,带头结点的单链表
{
    p=L,j=0;
    while(!p && j<i-1)
    {
        p=p->next;
        ++j;
    }
    s=new LNode;
    s->data=e;
    s->next=p->next;//画个图更容易理解
    p->next=s;
    return ok;
}

双链表的插入

跟单链表特别相似,就是将前后两个指针域都利用上,两个都是从插入的后指针域开始操作,从后往前。

//双向链表的插入
Status LinkInsertDuL(DuLinkList &L,int i,ElemType e)//在第i个位置之后插入
{
    p=GetElemDuL(L,i);//调用之前的查找函数
    if(p=NULL)//判断p是否为空
    {
        return ERROR;
    }
    s=new DuLNode;
    s->data=e;
    s->next=p->next;//插入一般都是从插入的后指针开始,画个图容易理解,跟单链表放在一起比较
    p->next->prior=s;
    s->prior=p;
    p->next=s;
    return OK;

}

5)删除

单链表的删除

就是将删除结点的前结点指向删除结点的后节点,将删除结点架空。

//删除
Status ListDelete(LinkList &L,int i)//删除第i个元素
{
    p=L,j=0;
    while(!p && j<i-1)
    {
        p=p->next;
        ++j;
    }
    if(p->next==NULL || j>i-1 )//判断前后两端位置是否合理
    {
        return ERROR;
    }
    q=p->next;
    p->next=q->next;
    delete q;//c++中能用,也可以用free;
    return OK;
}

双链表的删除

跟单链表一个性质,前后两个结点都利用上。

//双链表的删除
Status ListDeleteDuL(DuLinkList &L,int i)
{
     p=GetElemDuL(L,i);//调用之前的查找函数
     if(p==NULL)
     {
         return ERROR;
     }
     p->prior->next=p->next;
     p->next->prior=p->prior;
     return OK;
}

6)创建单链表

前插法

从头结点后面依次插入。

//前插法
void CreateListH(LinkList &L,int n)//从L的后面依次插入
{
    L=new LNode;
    L->next=NULL;
    for(i=0;i<n;i++)
    {
        p=new LNode;
        cin>>p->data;
        p->next=L->next;
        L->next=p;

    }
}

后插法

从链表的末尾插入。

//后插法
void CreateListR(LinkList &L,int n)//依次从最后插入
{
    L=new LNode;//这是个头指针
    L->next=NULL;
    r=L;//尾指针
    for(i=0;i<n;i++)
    {
        p=new LNode;
        cin>>p->data;
        r->next=p;//这里不能L,为了后续循环方便
        p->next=NULL;
        r=p;//每次调动尾指针
    }
}

2.3顺序表与链表的比较

顺序表:

优点:支持随机存储、存储密度高

缺点:大片连续空间分配不方便,改容量不方便。

链表:

优点:离散的小空间分配方便,改容量方便。

缺点:不可随机存储,储存密度低。

顺序表多用于表长可预估、查询(搜索)操作较多时适用。

链表多用于难以预估、经常要增加/删除元素是适用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值