当前位置:网站首页>指针学习日记(四)使用结构与指针(链表)

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

2022-07-22 18:10:00 潇湘夜雨寒

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没有变,所以该链表不会出事。

原网站

版权声明
本文为[潇湘夜雨寒]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_42677487/article/details/124621269