PZK学数据结构之链表(史上最详细思路和代码注释)(完整代码我放在最后面了,可以直接跑,方便大家cv编程)
文章目录
前言
在增删的指定节点操作就用到了查,大家可以看完增删的前两个就去看看查是怎么操作的,然后方便对指定节点操作。
本篇文章是交大家如何用结构体指针实现增删查改,
一、链表是什么?
百度百科链表:链表是一种物理存储单元上非连续、非顺序的存储结构,
数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
我的理解:多个有指针域的结构体的通过指针顺序链接在一起, 在内存中的存储是散落的
2.1图解数组和链表的存储
在内存如下存储:
---------------------------------------------------------------------------------------------------------------------------------------------------------------
2.2简单实现链表的两种方法,第一种是用结构体,第二种是用结构体指针
代码如下(示例):
2.2.1实现链表1
#include <stdio.h>
#include <stdlib.h>
struct Test//结构体定义
{
int data;
struct Test *next;
};
int main()
{
struct Test t1={
1,NULL};
struct Test t2={
2,NULL};
struct Test t3={
3,NULL};
t1.next=&t2;//链表精髓在这,每个节点的next存放的是下一个节点的地址。这样就连接起来了。
t2.next=&t3;
}
2.2.1实现链表2
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node
{
int data;
struct node * next;
}node,*pnode;//node是取别名,pnode是类型,结构体指针类型
//struct node * pnode
//创建头节点,初始化函数。返回头节点的指针。
pnode init()
{
pnode head = (pnode )malloc(sizeof(node)); //用malloc开辟空间,此时pnode == struct node *
if(head == NULL)//此时做一个容错判断,如果没有开辟成功,打印错误
{
perror("head fault");
}
head->data = 0;//开辟空间之后里面是没有值的,最好给数据域和指针域分别赋值
head->next = NULL;//指针没有指向,指向NULL就ok,防止其乱指向
return head;//返回头节点指针,方便我们以后调用
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------
二、本文实现的几个功能
链表的增加
链表的删除
链表的查找
链表的改动
---------------------------------------------------------------------------------------------------------------------------------------------------------------
三、链表的增加
在内存如下演示:
实现思路:(博主比较懒,三种插法只详细写了一个思路,思路都大同小异,我在每个插法代码的前面都画了内存操作图,里面有简单思路,每一行代码里面都给了注释,不理解的可以评论区留言呀)
第一步,创建新节点,然后把传递的值赋值给新节点
pnode pnew = (pnode )malloc(sizeof(node));//用malloc开辟空间,类型是pnode,大小是一个结构体的大小
第二步,写一个容错判断,如果pnew==NULL,说明创建不成功,直接退出
第三步:链接新节点到链表头下一个节点,何为链接,无非就是把下个节点的地址赋值给头节点的next;
pnew->next = head->next;//head->next原本存的是第二个节点的地址,现在把它赋值给新节点,那么是不是新节点的下一个就是原先的第二个节点了,就是实现图中1
第四步:把头结点和新节点连接起来
head->next = pnew;//此时,我们在把新节点和头节点链接起来,这样就是头节点指向新节点了,pnew本身就是一个指针
3.1头插法:每次都在头结点的后面插入
//每次都在头结点的后面增加,简称头插法
/****************************************************************
* 函数名: insertHead
* 参 数: head 链表的头节点指针
* data 需要插入节点数据
* 返回值: 链表中节点个数
* 节点的个数保存在head的data中。
****************************************************************/
int insertHead(node* head,int data)
{
//第一步:创建新节点,存入数据
pnode pnew = (pnode )malloc(sizeof(node));//用malloc开辟空间,类型是pnode,大小是一个结构体的大小
if(NULL == pnew)//容错判断新创建的节点是否成功
{
perror("head NULL");
exit(0);//不成功就输出错误,然后退出
}
pnew->data = data;//把传进来的值赋值给新节点
//第二步:链接新节点到链表头下一个节点,何为链接,无非就是把下个节点的地址赋值给头节点的next;
//head的next为空的情况
pnew->next = head->next;//head->next原本存的是第二个节点的地址,现在把它赋值给新节点,那么是不是新节点的下一个就是原先的第二个节点了
//第三步:head不为空,把头节点的next指针指向新的节点
head->next = pnew;//此时,我们在把新节点和头节点链接起来,这样就是头节点指向新节点了,pnew本身就是一个指针
//当第二步赋值的时候,头节点与原先的第二个节点链接自动断开
//第四步:节点个数加一
(head->data)++;//因为我们头节点的数据域存的是节点个数
//第五步:返回头节点中节点数据;
return head->data;
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------
3.2尾插法:每次都在链表的最后面插入
在内存如下演示:
/****************************************************************
* 函数名: insertEnd
* 参 数: head 链表的头节点指针
* data 需要插入节点数据
* 返回值: 链表中节点个数
* 节点的个数保存在head的data中。
****************************************************************/
int insertEnd(pnode head,int data)
{
//第一步:定义临时指针
node* ptmep = head;
//第二部:遍历链表,找最后一个节点
while( ptmep->next != NULL)
{
ptmep = ptmep->next;//指针偏移
}
//循环完之后,ptemp的next已经为NULL了
//第三步:创建新节点
pnode pnew = (pnode)malloc(sizeof(node));//malloc开辟空间
//第四步:给节点赋值
pnew->data = data;
//第五步:新节点插入到链表末尾
pnew->next = NULL;//尾插法,新节点需放在最后,所以新节点后面没有节点了,指向null
ptmep->next = pnew;//原最后一个节点指向新节点,那么原最后一个节点就成为了倒数第二个节点
//第六步:返回链表长度
(head->data)++;
return head->data;//也可以直接return ++(head->data);一样的效果
}
------------------------------------------------------------------------------------




958

被折叠的 条评论
为什么被折叠?



