数据结构之链表

       链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。(摘自百度百科)
       链表的操作方法域线性表类似,都用插入、删除、清空、销毁等功能。具体如下:
       1.创建一个结点并对头节点进行初始化  
struct LNode
{
    int data;
    struct LNode *next;
};

struct LNode* InitList()
{
    struct LNode *phead;//定义并返回一个头指针
    phead=(struct LNode *)malloc(sizeof(struct LNode));
    phead->next=NULL;
    return phead;
}
       2.在链表尾插入新结点
void ListInsert(struct LNode *l,int e)//在链表末尾插入新结点
{
    struct LNode *pnew;//定义一个结构体指针
    pnew=(struct LNode *)malloc(sizeof(struct LNode));//给该指针开一个结构体的空间
    pnew->data=e;//将要插入的数组e赋值到数据域中
    pnew->next=l->next;//因为在插入结点前指针l指向最后一个结点,故l->next此时等于NULL,在插入pnew所指向的结构体后,该节点为链表的末尾,故将指针pnew的指针域赋为NULL
    l->next=pnew;//将结构体变量pnew所指向的结构体链接到结构体指针l所指向的结构体后,即在链表末尾插入新的一个结构体
}
       3.输出整个链表
void DisplayList(struct LNode *l)//输出当前所存在的整个链表
{
    while(l->next!=NULL)//遍历到链表指针域为空(NULL),即遍历输出到链表结束
    {
        printf("%d ",l->next->data);
        l=l->next;
    }
    printf("\n");
}
      4.销毁整个链表
void deleteList(struct LNode *l,int id)//销毁链表
{
    int cnt=0;
    while(l->next!=NULL)
    {
        cnt++;
        if(cnt==id)//当链表存在要删去的第id的结点时,循环到id个结点进行相应的操作。
        {//因为头节点的存在,所以此时指针l指向的时要删除的结点的上一个结点,换句话说,头节点除外,每个结点的地址保存在上一个结点的指针域中
            struct LNode *p;//用来存的是要删除节点的地址
            p=l->next;
            l->next=l->next->next;//将要删除结点的上一个节点的指针域更新为要删除结点的指针域的值,即将上一个结点与下一个结点链接起来
            free(p);//清空要删除的结点
            break;
        }
        l=l->next;
    }
}
        5.清空链表所有结点
void DestroyList(struct LNode *l)//遍历清空链表
{
    struct LNode *p;
    while(l!=NULL)
    {
        p=l->next;
        free(l);
        l=p;
    }
}
       6.遍历到的链表长度
int ListLength(struct LNode *l)//得到链表长度
{
    int cnt=0;
    l=l->next;
    while(l!=NULL)
    {
        cnt++;
        l=l->next;
    }
    return cnt;
}
        7.遍历得到一个数值在链表中的位置
int LocateList(struct LNode *l,int e)//遍历得到一个数值在链表中的位置
{
    int cnt=0;
    while(l->next!=NULL)
    {
        cnt++;
        if(l->next->data==e)
        {
            return cnt;
        }
        l=l->next;
    }
    return Error;
}
        8.遍历输出链表第id个结点的数据域的数值
int GetList(struct LNode *l,int id)//遍历输出链表第id个结点的数据域的数值
{
    int cnt=0;
    while(l->next!=NULL)
    {
        cnt++;
        if(cnt==id)
            return l->next->data;
    }
    return Error;
}

完整代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Error -10000
struct LNode
{
    int data;
    struct LNode *next;
};
struct LNode* InitList()
{
    struct LNode *phead;//定义并返回一个头指针
    phead=(struct LNode *)malloc(sizeof(struct LNode));
    phead->next=NULL;
    return phead;
}
void DestroyList(struct LNode *l)//遍历清空链表
{
    struct LNode *p;
    while(l!=NULL)
    {
        p=l->next;
        free(l);
        l=p;
    }
}
int ListLength(struct LNode *l)//得到链表长度
{
    int cnt=0;
    l=l->next;
    while(l!=NULL)
    {
        cnt++;
        l=l->next;
    }
    return cnt;
}
void ListInsert(struct LNode *l,int e)//在链表末尾插入新结点
{
    struct LNode *pnew;//定义一个结构体指针
    pnew=(struct LNode *)malloc(sizeof(struct LNode));//给该指针开一个结构体的空间
    pnew->data=e;//将要插入的数组e赋值到数据域中
    pnew->next=l->next;//因为在插入结点前指针l指向最后一个结点,故l->next此时等于NULL,在插入pnew所指向的结构体后,该节点为链表的末尾,故将指针pnew的指针域赋为NULL
    l->next=pnew;//将结构体变量pnew所指向的结构体链接到结构体指针l所指向的结构体后,即在链表末尾插入新的一个结构体
}
void deleteList(struct LNode *l,int id)//销毁链表
{
    int cnt=0;
    while(l->next!=NULL)
    {
        cnt++;
        if(cnt==id)//当链表存在要删去的第id的结点时,循环到id个结点进行相应的操作。
        {//因为头节点的存在,所以此时指针l指向的时要删除的结点的上一个结点,换句话说,头节点除外,每个结点的地址保存在上一个结点的指针域中
            struct LNode *p;//用来存的是要删除节点的地址
            p=l->next;
            l->next=l->next->next;//将要删除结点的上一个节点的指针域更新为要删除结点的指针域的值,即将上一个结点与下一个结点链接起来
            free(p);//清空要删除的结点
            break;
        }
        l=l->next;
    }
}
int LocateList(struct LNode *l,int e)//遍历得到一个数值在链表中的位置
{
    int cnt=0;
    while(l->next!=NULL)
    {
        cnt++;
        if(l->next->data==e)
        {
            return cnt;
        }
        l=l->next;
    }
    return Error;
}

int GetList(struct LNode *l,int id)//遍历输出链表第id个结点的数据域的数值
{
    int cnt=0;
    while(l->next!=NULL)
    {
        cnt++;
        if(cnt==id)
            return l->next->data;
    }
    return Error;
}
void DisplayList(struct LNode *l)//输出当前所存在的整个链表
{
    while(l->next!=NULL)//遍历到链表指针域为空(NULL),即遍历输出到链表结束
    {
        printf("%d ",l->next->data);
        l=l->next;
    }
    printf("\n");
}
int main()
{
    struct LNode *phead;
    phead=InitList();
//    ListInsert(phead,1);
//    ListInsert(phead,2);
//    ListInsert(phead,3);
//    ListInsert(phead,4);
//    ListInsert(phead,5);
//    DisplayList(phead);
//    deleteList(phead,3);
//    DisplayList(phead);
//    printf("%d",LocateList(phead,3));
    return 0;
}

希望对大家有所帮助! 大笑


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值