对于链表的总结

# 链表

### 链表是什么呢?

链表和数组一样同属于线性表,即一种线性存储结构,它可分为两种,即顺序存储结构和链式存储结构,前者其特点是逻辑关系上相邻的两个元素在物理上也相邻,而链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构

**特点:** 

用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的

可分为单链表,双向链表,循环链表,静态链表

### <u>**操作(只讲单链表):**</u>

**//单链表的存储结构**

```c
typedef struct LNode
{
    ElemType data//结点的数据域
    struct LNode *next;//结点的指针域(LNode *定义指向单链表中任意结点的指针变量)
}LNode,*LinkList;//LinkList为指向结构体LNode的指针类型
```

这里定义的是单链表中每个结点的存储结构,它包括两部分:存储结点的数据域data,其类型通用类型标识符ElemType表示;存储后继结点位置的指针域next,其类型为指向结点的指针类型LNode*

对于我来说,首元结点,头结点,头指针容易弄混,加以说明:

1.首元结点是指链表中存储第一个数据元素的结点

2.头结点是在首元结点之前附设的一个结点,其指针域指向首元结点。头结点的数据域可以不存储任何信息,也可存储与数据元素类型相同的其他附加信息

3.头指针是指向链表中第一个结点的指针。若链表设有头结点,则头结点所指结点为线性表的头结点;若链表不设头结点,则头指针所指结点为该线性表的首元结点

**//初始化**

```c
Status InitList(LinkList &L)
{
    head=(LNode*)malloc(sizeof(LNode));//生成新结点作为头结点,用头指针L指向头结点
    L->next=NULL;//头结点的指针域置空
    return OK;
}
```

**//取值**

```c
(根据序号i获取元素的值,用e返回L中第i个数据元素的值
Status GetElem(LinkList &L,int i,ElemType &e)
{
    p=L->next,j=1;//初始化,p指向首元结点,计数器j初值赋为1
    while(p!=NULL&&j<i)//顺链域向后查找,直到p为空或p指向第i个元素
    {
        p=p->next;//p指向下一个结点
        j++;//计数器相应加一
    }
    if(p==NULL||j>i)//i值不合法
        return ERROR;
    e=p->data;//取第i个结点的数据域
    return OK;
}
```

**//查找**

```c
(在单链表中查找值为e的元素)
LNode *LocateElem(LinkList L,ElemType e)
{
    p=L->next;//初始化,p指向首元结点
    while(p!=NULL&&p->data!=e){//顺链域向后查找,直到p为空域或p所指结点的数据域为e
        p=p->next;//p指向下一个结点
    }
    return p;//查找成功返回值为e的结点地址p,查找失败p为NULL
}
```

**//插入**

```c
(将值为e的新结点插入表的第i个结点的位置)
Status ListInsert(LinkList &L,int i,ElemType e)
{
    p=L,j=0;
    while(p!=NULL&&j<i-1)
    {
        p=p->next;//查找第i-1个元素,p指向该结点
        j++;
    }
    if(p==NULL||j>i-1)
        return ERROR;
    s=(LNode*)malloc(sizeof(LNode));//生成新结点*s
   s->data=e;//将结点*s的数据域置为e
   s->next=p->next;//将结点*s的指针域指向结点ai
    p->next=s;//将结点*p的指针域指向结点*s
    return OK;
}
```

和顺序表一样,如果表中有n个结点,则插入操作中合法的插入位置有n+1个,即1<=i<=n+1。当i=n+1时,新结点则插在链表尾部

**//删除**

```c
(在带头结点的单链表L中,删除第i个元素)
Status deletelist(LinkList &L,int i)
{
    p=L,j=0;
    while((p->next!=NULL)&&(j<i-1))//查找第i-1个结点,p指向该结点
    {
        p=p->next;
        j++;
    }
    if((p->next==NULL)||(j>i-1))
        return ERROR;
    q=p->next;//临时保存被删结点的地址以备释放
    p->next=q->next;//改变删除结点前驱结点的指针域
    delete(q);//释放删除结点的空间
    return OK;
}
```

**//创建单链表(前插法和后插法)**

```c
/头插法(逆位序输入n个元素的值,建立带表头结点的单链表L)
void creatlist(LinkList &L,int n)
{
    L=(LNode*)malloc(sizeof(LNode));
    L->next=NULL;
    for(i=0;i<n;i++){
            p=(LNode*)malloc(sizeof(LNode));
        scanf("%d",p->data);
    p->next=L->next;
    L->next=p;
    }
}

//后插法(正位序输入n个元素的值,建立带表头结点的单链表L)
void creatlist(LinkList &L,int i)
{
    L=(LNode*)malloc(sizeof(LNode));//生成新结点
    L->next=NULL;
    r=L;//尾指针指向头结点
    for(i=0;i<n;i++){
        p=(LNode*)malloc(sizeof(LNode));//生成新结点
        scanf("%d",&p->data);//输入元素值赋给新结点*p的指针域
        p->next=NULL;
        r->next=p;//将新结点*p插入尾结点*r之后
        r=p;//r指向新的尾结点*p
    }
}
```

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值