线性表的链式存储结构

本文探讨了线性表的链式存储结构,指出顺序存储在大规模数据时的不便,尤其是插入和删除操作。链式存储通过小节点连接大业务节点,简化操作。文中介绍了链式表的基本操作,如创建和插入,并提供了创建链表和插入节点的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线性表的链式存储结构

在开始说链式存储之前我们先回顾一下传统的单链表以及链表的发展过程

传统单链表的节点是这样的
typedef struct lnode{

datatype data; //数据域

struct lnode *next; //指针域

}LNode,*LinkedList;

这样有什么样的缺点,我们观察可以发现每个节点分为数据域和指针域两部分,指针域指向的是和它一模一样的节点,用一幅图来展示就是这样:

在这里插入图片描述
但是如果是这样的呢?
在这里插入图片描述
为了解决这个问题就产生一种新的链表:
在这里插入图片描述
其核心思想就是用一些小的节点将我们的大的业务节点串联起来,代码如下:

小节点
typedef struct _tag_LinklistNode
{
struct _tag_LinklistNode *next;
}LinkListNode;

大节点
typedef struct Teacher
{
LinkListNode node;//小节点
int age;
char name[64];
}Teacher;

前言到这里就结束了,下面开始正文!
线性表的顺序存储结构存在许多不便之处,其中尤其体现在插入删除操作中(假如有一亿数据呢),而链式存储由于节点之间在内存中不连续,所以不涉及大量的元素移动。
链式表的基本操作与顺序表类似:创建,插入,删除,求长度,取元素,清空,销毁等等,下面将重点介绍创建,插入。

创建一个线性表
创建时一般会有一个头节点,与首节点不同的是头节点不存数据,这样设计的好处是后续头部插入等操作可以和后面普通位置插入时保持一致。

模型大致如下:
在这里插入图片描述
代码如下:

	typedef struct _tag_LinklistNode
	{
	    struct _tag_LinklistNode *next;
	}LinkListNode;  //小节点
	
	typedef struct Teacher
	{
	    LinkListNode node;//小节点
	    int age;
	    char name[64];
	}Teacher;
	
	typedef struct _tag_LinkList
	{
	    int length;
	    LinkListNode  header;
	}TLinkList; //头节点 其中可以保存长度、首节点地址信息。

所以创建一个链式表就是malloc一个头节点,然后后续插入大节点即可形成一条链表。

LinkList* LinkList_Creat()
{
    TLinkList *ret = NULL;

    ret = (TLinkList *)malloc(sizeof(TLinkList));
    memset(ret,0,sizeof(TLinkList));
    ret->length = 0;
    ret->header.next = NULL;

    return ret;
}

接下来说一下链表的插入操作,还是用一幅图来表示:
首先我们设置一个current辅助指针指向header,假如我们要插入1号位置节点。
在这里插入图片描述
我们利用一个循环,将current向后跳动至要插入位置的前一个元素:
在这里插入图片描述
对应代码如下:

for(i = 0;i<pos;i++)
{
current = current->next;
}

接下来分为三个步骤,打断,新建,新建:
在这里插入图片描述
对应代码如下:

node->next = current->next;
current->next = node;
//实际上打断操作在代码中不体现

其他基本操作与顺序表类似,这里不再赘述,直接上完整源码,供大家调试:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
typedef void LinkList;
typedef struct _tag_LinklistNode
{
    struct _tag_LinklistNode *next;
}LinkListNode;
typedef struct Teacher
{
    LinkListNode node;//小节点
    int age;
    char name[64];
}Teacher;

//数据域
typedef struct _tag_LinkList
{
    int length;
    LinkListNode  header;
}TLinkList;
LinkList* LinkList_Creat()
{
    TLinkList *ret = NULL;

    ret = (TLinkList *)malloc(sizeof(TLinkList));
    memset(ret,0,sizeof(TLinkList));
    ret->length = 0;
    ret->header.next = NULL;

    return ret;
}

void LinkList_Destory(LinkList* list)
{
    if(list != NULL)
    {
        free(list);
        list = NULL;

    }
    return ;
}
//链表恢复到初始状态
void LinkList_Clear(LinkList* list)
{
    TLinkList *tlist = NULL;
    if(list == NULL)
    {
        return ;
    }
    tlist = (TLinkList *)list;
    tlist->length = 0;
    tlist->header.next = NULL;
    return ;
}

int LinkList_Length(LinkList* list)
{
    TLinkList *tlist = NULL;
    if(list == NULL)
    {
        return -1;
    }

    tlist = (TLinkList *)list;
    return tlist->length;
}
//因为链表是单向的,三号位置保存在二号位置的next域中
//指针指向谁,就把谁的地址付给指针
//分清楚链表的操作逻辑和辅助指针变量之间的关系

int LinkList_Insert(LinkList *list,LinkListNode* node,int pos)
{
    int i = 0;
    int ret = 0;
    LinkListNode *current = NULL;

    TLinkList * tlist = (TLinkList*)list;
    if(list == NULL || node == NULL || pos < 0)
    {
        ret =  -1;
        printf("func LinkList_Insert error :%d",ret);
        return ret;
    }
    
    current = &(tlist->header);

    for(i = 0;i<pos;i++)
    {
        current = current->next;
    }
    node->next = current->next;
    current->next = node;

    tlist->length ++;
    return 0;
}

LinkListNode* LinkList_Get(LinkList* list,int pos)
{
    int i;
    int ret = 0;
    LinkListNode *current = NULL;

    TLinkList * tlist = (TLinkList*)list;
    if(list == NULL || pos < 0)
    {
        ret =  -1;
        printf("func LinkList_Insert error :%d",ret);
        return NULL;
    }
    
    current = &(tlist->header);

    for(i = 0;i<pos;i++)
    {
        current = current->next;
    }
    
    return current->next;
}

LinkListNode* LinkList_Delete(LinkList* list,int pos)
{ 
    int i;
    int tmp = 0;
    LinkListNode *current = NULL;

    LinkListNode *ret = NULL;

    TLinkList * tlist = (TLinkList*)list;
    if(list == NULL ||  pos < 0)
    {
        tmp =  -1;
        printf("func LinkList_Insert error :%d",tmp);
        return NULL;
    }
    
    current = &(tlist->header);

    for(i = 0;i<pos;i++)
    {
        current = current->next;
    }
    //缓存要删除节点的位置
    ret = current->next;

    //连线
    current->next = ret->next;
    tlist->length --;
    return ret;
}
int main()
{
    LinkList* list = NULL;
    int ret,i;
    Teacher t1,t2,t3,t4,t5;
    t1.age = 31;
    t2.age = 32;
    t3.age = 33;
    t4.age = 34;
    t5.age = 35;
    list = LinkList_Creat();

    ret = LinkList_Insert(list,(LinkListNode *)(&t1),0);
    ret = LinkList_Insert(list,(LinkListNode *)(&t2),0);
    ret = LinkList_Insert(list,(LinkListNode *)(&t3),0);
    ret = LinkList_Insert(list,(LinkListNode *)(&t4),0);
    ret = LinkList_Insert(list,(LinkListNode *)(&t5),0);
    
    for(i = 0;i<LinkList_Length(list);i++)
    {
        Teacher *tmp = (Teacher *)LinkList_Get(list,i);
        if(tmp == NULL)
        {
            return 0;
        }
        printf("tmp->age:%d\n",tmp->age);
    }
    printf("length = %d\n",LinkList_Length(list));
    for(i = 0;i<4;i++)
    {
        LinkList_Delete(list,0);   
    }
    
    for(i = 0;i<LinkList_Length(list);i++)
    {
        Teacher *tmp = (Teacher *)LinkList_Get(list,i);
        if(tmp == NULL)
        {
            return 0;
        }
        printf("tmp->age:%d\n",tmp->age);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值