指针学习日记(四)使用结构与指针(链表)

本文详细解析了C语言中链表插入操作的实现,从基本的插入函数到针对边界情况的优化。讨论了指针在链表操作中的关键作用,以及如何处理可能的错误情况,如插入值小于链表首元素或大于所有元素的情况。通过逐步改进代码,展示了如何确保链表的正确性和稳定性。

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

typdef struct node
{
struct node *link;
int value;
}Node
;

Node* new;//创建指向结构体的指针new

new = (node*)malloc(sizeof(node));
这个语句我想专门来解释一下。
首先,new是个指向结构体的指针变量。
其次,malloc是void指针,这就意味着它可以转变为任何类型的指针,
而(node
)就是强制转换符。将返回值强制转会成结构体形的指针(与new类型相同),而sizeof(node)就是分配这个大小的内存空间给new。

链表:
大一上学期时老师教到指针的时候,很多同学并不了解指针的运用,然后只知道指针是学C和C++时很令人头疼的一节,当然甚至有些同学在下课时大声谈论“C和C++完全可以不学,指针麻烦死了,以后学JAVA走前端不香吗”。这个吧,本人目前也大一,咱也不知道说的对还是不对,但是如奥力给大叔说的那样,遇到困难,要微笑着面对它。如果指针这一关不过,c和c++基本上就走到尽头了,少了c和c++的陪伴,我想怎么说以后必然要付出一定代价(是不是扯得有点远了?)总之,许多同学大一下学数据结构时的第一个梦魇便是链表,链表恐怕是基本上所有初学者第一个大规模使用指针的程序。

typedef struct NODE
{
        struct NODE *link;
		int          value;
}Node;//typedef定义符,未来可以直接用Node定义新值

#include<stdlib.h>
#include<stdio.h>
/*这里就专门用插入函数来解释吧*/

/此处代码借鉴了部分《C和指针》中的教学代码有兴趣者可以查阅原书/
int insert(Node* current,int new_value)
{
	Node* previous;
	Node* new;
	
	while(current->value < new_value)
	{
		previous = current;
		current = current->link;
	}
	
	new = (Node*)malloc(sizeof(Node));
	if(new = NULL)
	{
		return -1;
	}
	
	new->value = new_value;

	new->link = current;
	previous->link = new;
	return 1;
}

是不是感觉这个代码不错?错,这个代码有局限性,倘若插入的值已经比第一个值要小,
那么系统会报错!因为一开始就没有while循环,previous根本没有被赋值,间接访问一个NULL的值是不被允许的!
并且如果输入一个比所有值都要大的值也是不行的,此时current指向的值也是NULL,不可对一个NULL的指针间接访问!
所以我们可以对循环进行改进

while(current->value < new_value&&current!=NULL{
	previous = current;
	current = current->link;
}

但是认真想的就会发现,这只能解决第二种问题,第一种问题还未解决。
我们不妨对此进行一次彻底的优化,不论是在首位插入还是尾端插入都是特殊情况。

消除特殊情况的关键在于:我们必须认识到,链表中的每个节点都有一个指向它的指针。对于第一个节点,这个指针是根指针;对于其他节点,这个指针是前一个节点的link字段。重点在于每个节点都有一个指针指向它!

#include<stdlib.h>
#include<stdio.h>

int insert(Node** linkp,int new_value)//linik是指向治指针的指针
{
	Node* current;
	Node* new;
    while((current = *linkp) != NULL && current->value < new_value)
    {
    	linkp = &current->link;
    	//我们调用类中的成员或者结构体中的成员时 我们就需要使用 -> 运算符
    }
    
    new = (Node*)malloc(sizeof(Node));
    if(new == NULL)
    {
    	return -1;
    }
    new->value = new_value;
	
	new->link = current;
	*linkp = new;
	
	return 1;
}

到现在还是很佩服此优化,将需要更改的地址赋值给linkp,再将current赋值给new->link,因为current->link没有变,所以该链表不会出事。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值