对线性表理解以及C语言实现链表的插入删除等操作。

我们首先用一个结构体定义链表的储存结构,代码如下。

#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
/*-------------线性表的链式储存结构-----------------*/
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;
typedef int Status;

在链表L中第i个元素之前插入一个新的元素:我们需要找到第i-1个结点,然后修改其指向后继的指针。假设新插入的元素e,新生成的结点为s,我们可以分为三个个步骤:1.让e的后继指向i-1的后继(也就是指向i),2.让i-1的后继的指针指向s,3.然后讲新插入的元素值赋给新插入结点的数据域。这样便插入了一个新的元素。代码如下:

Status ListInsert_L(LinkList *L,int i,ElemType e)/*在L中第i个元素之前插入新的元素e*/
{
    LinkList p,s;
    int j=0;
    p=*L;
    while(p&&j<i-1)   /*寻找第i-1个节点*/
    {
        p=p->next;   
        ++j;
    }
    if(!p||(j>i-1))return 0;/*i小于1或者大于表长加1*/
    s=(LinkList)malloc(sizeof(LNode));/*生成新的节点*/
    s->next=p->next;p->next=s;/*插入到L中*/
    s->data=e;
    return 1;
}

要想在链表L中删除第i个元素与插入元素的思路相同,找到第i-1个结点,然后修改其后继的指针。假设删除第i个结点,一个中间变量。1.我们首先找到第i-1个结点;2.q=p->next,p->next=q->next;这样i-1结点的后继指针便指向了i+1结点,我们可以然后删除q,便删除了第i个结点。代码如下:

Status ListDelete_L(LinkList *L,int i)/*删除L中第i个数据元素*/

{

    LinkList p,q;

    int j;

    p=*L;j=0;

    while(p->next&&j<i-1)/*寻找第i个结点,并令p指向其前驱*/

    {

        p=p->next;++j;

    }

    if(!p->next||(j>i-1))return 0;/*删除位置不合理*/

    q=p->next;p->next=q->next;/*删除并释放结点*/

    free(q);

    return 1;

}

取出链表L中第i个元素的值:因为单链表是一种顺序储存结构,因此如果想要找到第i个元素首先需要找到第i-1个元素,

184634_iehE_2537692.png

基本操作为移动指针,比较j和i,指针p始终指向链表中的第j个元素。代码如下:

Status GetElem_L(LinkList L,int i,ElemType *e)/*取出链表L中第i个元素的值*/
{
    LinkList p;int j;
    p=L;j=0;
    while(p&&j<i) /*寻找第i个结点*/
    {
        p=p->next;++j;
    }
    if(!p||j>i)return 0;
    *e=p->data;  /*用来返回第i个结点的值*/
    return 1;
}

查询链表L中与e元素相同的第一次出现的位序:我们可以遍历整个链表,找到元素后返回位序,并停止遍历;代码如下:

 Status LocateElem_L(LinkList *L,ElemType e,int *n/*,compare()*/)/*查询链表中与e相同元素的第一个值*/
{                                                                /*并用n返回其位置*/
    LinkList p;
    int j=0;
    p=*L;
    while(p)/*判断p是否为空*/
    {
        p=p->next;++j;
        if(p->data==e)/*判断p所指向的数据的值是否与e相等*/
        {
            *n=j;return 1;
            break;
        }
    }
 return 0;
}

逆序插入法生成一个链表:和插入思想相同,生成头结点函数写在了主函数(测试函数与)中,最后会有说明。代码如下:

void CreateList_L(LinkList *L,int n)/*逆序输入n个元素的值,n为链表元素的个数*/
{
    LinkList p,s;
    p=*L;
    for(n;n>0;--n)
    {   
        int tmp;
        s=(LinkList)malloc(sizeof(LNode));/*生成新的结点*/
        scanf("%d",&tmp);
        s->data=tmp;     /*插入元素的值*/
        s->next=p->next;p->next=s;  /*插入到表头*/
    }
}

输出链表所有的值:遍历链表所有元素并依次输出。代码如下:

Status ListTraverse(LinkList *L)/*用于输出链表的所有值*/
{
    LinkList p;
    p=*L;
    p=p->next;/*让p指向第一个结点*/
    while(p)/*判断p是否为空*/
    {
        printf("%d\t",p->data);/*输出元素的值,并让p指向下一个结点*/
        p=p->next;
    }
    printf("\n");
    return 0;
}

测试链表的长度:代码如下:

 Status ListLenght_L(LinkList *L)/*用于测链表的长度*/
{
    int j=0;
    LinkList p=*L;
    while(p)/*判断p是否为空*/
    {
        j++;
        p=p->next;
    }
    return j;
}

 

接下来我们测试一下程序的运行结果,在测试程序中生成的链表元素个数为5,结点的个数(包含头结点)为6。1.输入的数据为11,12,13,14,15;2.逆序生成链表输出;3.在第四个元素之前插入“8”然后输出;4.删除第四个元素在输出;5.取出第二个元素的值;6.链表的长度;7.返回元素"11"的位序。代码如下:

void main()/*测试函数*/
{
 int n,n1,ex;/*用n表示取出元素的值,n1表示测试链表的长度,ex表示第一个与元素e相等的位置*/
    LinkList L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
 printf("请输入5个元素,用来逆序生成链表:");
    CreateList_L(&L,5);/*我们设置为5个元素*/
 printf("生成的链表为:");
    ListTraverse(&L);
 ListInsert_L(&L,4,8);
  printf("在第四个元素前面插入元素8:生成的链表为:");
    ListTraverse(&L);
    ListDelete_L(&L,4);/*删除第四个结点*/
  printf("删除第四个元素生成的链表为:");
    ListTraverse(&L);
    GetElem_L(L,2,&n);/*取出第二个元素的值*/
    printf("第二个元素的值为:%d\n",n);
    n1=ListLenght_L(&L);/*用来求链表的长度*/
    printf("链表的长度为:%d\n",n1);
   if( LocateElem_L(&L,11,&ex))/*查找与元素11相同的位序*/
   {
    printf("与元素11相同的元素的位序为:%d\n",ex);
   }
   else
   {
    printf("与元素11相同的元素的位序为:查找失败");
   }
    system("pause");
}

运行结果如下:

193451_2bt0_2537692.png

总结:

优点:1.它是一种动态储存结构,整个储存空间供多链表共用;2.使用时不用预先分配空间;3.插入删除方便;

缺点:1.指针占用额外储存空间,;2.不能随机存取,查找速度慢;

-------------------------------------------------------------------------华丽分割线-----------------------------------------------------

学习数据结构链表后记录,有错误的欢迎指正。

转载于:https://my.oschina.net/wang520/blog/646203

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值