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