c语言建立链表叫LNode,C语言实现链表

链表是数据结构最为基础的一种 学习之后想要自己实现一下 所以就开了一个长期更新的博客 记录自己实现各种数据结构的帖子 都是一些比较基础的

链表由一系列不必在内存中连续的结构组成。每一个结构都含有表元素和指向包含该元素的后继元的结构的指针,我们称之为Netx指针,最后一个单元的Next指针指向NULL,即指向空;因此就有以下定义的结构体表示的链表节点:

/*定义线性链表的结构*/

typedef struct LNode

{

int date;//数据域

struct LNode *next;//指向下一个节点的指针,即指针域

}LNode;

有了节点之后,我们就需要创建一个链表,因此用以下函数来创建一个带有头结点的链表(该创建方法被称为尾插法)e68ef3fbe7cbd020afdb2b259842a4a2.png

LNode* CreateList(int n)

{

LNode* s;

LNode* r;//分别创建用来指向新节点(s)和尾节点(r)的指针

/*我认为这里是对节点L的重复初始化,但是在主函数中不对节点L进行初始化会报错 L未被初始化*/

LNode *L = (LNode*)malloc(sizeof(LNode));

L->next = NULL;

r = L;

for (int i = 0; i < n; i++)

{

s = (LNode*)malloc(sizeof(LNode));//为新节点申请内存空间

printf("输入数据:");

scanf("%d", &s->date);

r->next = s;//将新节点“连接”在尾节点之后

r = s;//新节点变为尾节点

}

if(L->next != NULL)

r->next = NULL;//将尾节点的指针域置位空

return L;

}

成功创建了一个链表之后,相信很多人都想看看链表所保存的数据是不是自己所输入的数据,因此,我们就用一个遍历链表的函数将数据全部输出,并检查是否和自己所输入的数据相符合:

//遍历链表,输出数据

void OutputLinkList(LNode *L)

{

LNode* temp = L;//使用临时变量temp暂存头结点的值 防止遍历链表时头结点移动到尾节点导致链表丢失

while (temp->next != NULL)

{

//由于链表含有头结点 所以应该从链表的第二个节点开始输出并且依次后移

temp = temp->next;

printf("%d ", temp->date);

printf("\n");

}

}

注意,由于这是带有头结点的链表,所以应该从链表的第二个节点输出,上述代码已经说明,就会不赘述了

判断链表是否为空

//判断是否为空链表

void IsEmpty(LNode *L)

{

/*判断是否为空列表只需要判断头结点的指针域是否置空,若置空则为空链表,反之则为非空链表*/

if (L->next == NULL)

printf("空链表!");

else printf("非空链表!");

}

有了链表,我们当然就需要获取链表中指定位置的元素

//定位获取链表中某一个元素 参数position是指定的位置

int GetNode(LNode *L, int *n, int position)

{

LNode *P = L;//创建临时变量并赋值为头结点 以免后移时丢失头结点位置

int j = 0;//计数器 由于这是带有头结点的链表 头结点中的数据域数据位空 所以计数器从0开始

while ((P != NULL) && (j <= position))

{

//指针后移 查找指定元素

P = P->next;

++j;

}

//未查找到指定元素的条件

if ((P == NULL) || (j > position))

return false;

else

{

*n = P->date;

return true;

}

}

其中,应该注意区分获取指定元素和指定位置元素的区别,获取指定位置的元素指的是链表中第几个元素。

程序员的工作被称为增删改查,上面有了对链表的查,接下来介绍对链表的增·删·改

向链表中增加节点,也被称作向链表中插入节点:

//插入新节点到链表中指定的位置

LNode* InsertNode(LNode *L)

{

LNode *P = L;

int j = 0;//计数器 由于有数据域为空的头结点所以从0开始

int inser_position;//新节点将插入到position之前

printf("插入到链表中的位置:");

scanf("%d", &inser_position);

//定位第inset_position-1个节点的位置

while ((P != NULL) && (j < inser_position - 1))

{

P = P->next;

++j;

}

LNode *new_node = (LNode*)malloc(sizeof(LNode));//为新插入的节点申请内存空间

printf("输入节点的值:");

scanf("%d", &new_node->date);

new_node->next = P->next;

P->next = new_node;

return L;

}

231816445fc471c07634f7d9c3d307a8.png

由于链表在内存中的不连续性,所以要先将新节点和第position个节点链接起来,然后再讲第position-1个节点和新节点链接起来

链表节点的删除:

//删除链表中指定位置的节点

LNode* DeleteNode(LNode *L)

{

int j = 0;//计数器

LNode *P = L;

int delete_position;//删除节点的位置

printf("输入需要删除节点的位置:");

scanf("%d", &delete_position);

//寻找第delete_position - 1个节点的地址并保存在 P 中

while ((P->next != NULL) && j < delete_position - 1)

{

P = P->next;

++j;

}

if ((P->next == NULL) && (j > delete_position - 1))

{

printf("输入的位置非法,程序退出!\n");

return L;

}

LNode *Q = P->next;//记录第delete_position节点的地址

P->next = Q->next;//删除指定的节点

free(Q);//释放指定节点的内存空间

return L;

}

链表节点数据域的值改动过于简单就不做叙述,至此链表基本的增删改查全部介绍完。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值