链表(包括特殊的链表-栈和队列)

总结一下链表的用法,加深自己的印象也给自己和其他萌新做参考。

链表其实跟数组一样,都是线性表的一类,不同的在于数组是顺式存储结构,而链表则是链式存储结构,为什么有时候要用链表呢?因为链表在插入和删除元素的时候比数组更加有优势,并且它不用担心溢出的问题。当然能用数组解决的问题,就尽量别用链表了,因为链表功能的实现方面还是相对麻烦的。(个人意见)

一 单链表

首先最简单的链表,单链表,由结点组成,结点中包含数据域(放数据)和指针域(指向下一个结点的地址,从而达到连起来的效果),首先要建立一个链表,要先有一个头指针(而头结点不是必要的)。

/*线性表的单链表存储结构*/
typedef int ElemType;/*typedef 起到起别名的作用,以int为例,实际情况请灵活变通一下。
typedef struct Node
{
      ElemType data;/*数据域*/
      struct Node *next;/*指针域*/
}Node;
typedef struct Node *LinkList;/*定义LickList,后面声明指针用的*/
        

这个是建立结点用的结构体。(链表必要元素)

然后接着就是链表的建立了

/*假设一个首项为一,公差为一的递增数列输入到链表里,假设有8项*/
void CreatListHead(LinkList *L , int n)/*头插法,后入的编号在前面
{
      LinkList p;
      int i;
      *L = (LinkList)malloc(sizeof(Node));
      (*L)->next=NULL;        /*先建立一个带头结点的单链表*/
      for(i=0;i<8;i++){
           p=(LinkList)malloc(sizeof(Node));/*建立一个新结点,malloc的头问题是stdlib.h*/
           p->data=i+1;
           p->next=(*L)->next;
           (*L)->next=p;         /*相当于L的手不要NULL了,牵了p,而p牵了NULL*/
        }
}


链表数据的输入也可以在主函数里面,看个人,输入跟插入其实差不多。

后插法比较符合我们的正常思维,多了个指向尾部的指针,代码如下:

void CreatListTail(LinkList *L , int n )
{
      LinkList p,r;/*r为指尾部的指针*/
      int i;
      *L=(LinkList)malloc(sizeof(Node));
      r=*L;
      for(i=0;i<8;i++){
           p=(LinkList)malloc(sizeof(Node));
           p->data=i+1;
           r->next=p;
           r=p;
      }
      r->next=NULL;     /*表示链表结束 */
}
     

接下来介绍一下单链表的插入和删除。

插入就相当于把一个位置让给一个结点,这个位置的前面的结点把指针指向它,而这个插入的结点把指针指向后面的结点。

代码如下:

void InsertList(LinkList *L , int i ,  ElemType e )/* i为插入位置,e为插入的值*/
{
        LinkList p,s;
        int j=1;
        p=*L;
        while(p&&j<i){
        p=p->next;
        ++j;
        }
        if(!p||j>i)
        return  ERROR;
        s=(LinkList)malloc(sizeof(Node));
        s->data=e;
        s->next=p->next;/*将p的后继结点赋给s的后继*/
        p->next=s;/*p的后继指针指向s*/
        return OK;
}
         

删除则是反过来,可以看作忽略掉要删除位置的结点,然后其前面的结点的指针去指向其后面即可。需要去回收要删除的结点(free)。

代码如下:

void DeleteList (LinkList *L,int i,ElemType *e)/*需要返回删除的值e*/
{
        LinkList p,q;
        int j;
        p=*L;
        while(p&&j<i){
           p=p->next;
           ++j;
        }
        if(!p|j>i)
        return ERROR;
        q=p->next;/*p为删除位置的前一位,q为删除位置*/
        p->next=q->next;/*p的后继指针指向删除位置q的后继指针,即跳过q*/
        *e=q->data;
        free(q);/*其功能与malloc相反*/
        return OK;
}

猜你喜欢

转载自blog.csdn.net/zh1144237061/article/details/75114061
今日推荐