链表结构介绍及形状
链表添加及代码表示
#inlcude<stdio.h>
#include<stdlib.h>
typedef struct _node {//用typedef是为了后面不再需要打struct,节省时间
int value;
struct _node *next;//用struct是因为编译器还未到node,无法用node定义
} node;
int main()
{
int number;
node *head = NULL;
do{//先读入number,若用while,则不能先输入number
scanf("%d",&number);
if(number != -1)
{
//add to linked-list(将新元素加入链表)
node *p = (node*) malloc (sizeof(node));//申请一个_node大小的空间存放
p->value = number;
p->next = NULL;
//find the last(找到链表的最后一个结点)
node *last = head;//定义一个last的指针,指代最后一个结点的位置。在一开始链表没有元素时,直接跳到else
if( last )//当last不等于NULL,可以往下走
{
while( last->next )//当last->next不等于NULL时,令last指向结点内的指针元素,即指向下一个结点的首地址
{
last = last->next;
}
//attach(添加)
last->next = p;//链表最后一个结点的next由NULL指向了新添加的结点的首地址
}
else
{
head = p;//当last等于NULL时,head=p,使p成为了链表的第一个结点
}
}
}while(number != -1);
return 0;
}
链表函数
将main函数内,添加链表元素的代码独立成一个函数.
下面为错误代码,因为下面传递的是指向指针 head 的指针,而在 add 函数中修改了指针 head 的值,从而改变了 main 函数中的 head 指针指向的位置,这会影响链表结构的修改。因此需要传递指针的指针
因为head未指向任何东西,所以传进去add函数的为指针的地址,而
#include<stdio.h>
#include<stdlib.h>
typedef struct _node {
int value;
struct _node *next;
} node;
typedef struct _list{//
node *head;
}List;
void add(List *plist, int number)
{
//add to linked-list(将新元素加入链表)
node *p = (node*) malloc (sizeof(node));
p->value = number;
p->next = NULL;
//find the last(找到链表的最后一个结点)
node *last = plist->head;//从第一个开始找到最后结点
{
while( last->next )//当last->next不等于NULL时,令last指向结点内的指针元素,即指向下一个结点的首地址
{
last = last->next;
}
//attach(添加)
last->next = p;//链表最后一个结点的next由NULL指向了新添加的结点的首地址
}
else
{
plist->head = p;//当last等于NULL时,plist->head=p,使之记住第一个结点地址
}
}
int main()
{
int number;
List list;
list->head = NULL;
do{
scanf("%d",&number);
if(number != 0)
{
add(&list, number);
}
}while(number != 0);
return 0;
}
链表搜索
此循环可以遍历整个链表,输出每一个值,插在主函数"return 0"之前
node *p;
for(p = list.head; p; p = p->next)//遍历首地址为链表首地址;只要p还存在(即不到最后一个结点,不为NULL),遍历继续;每一次操作结束后指向下一个结点首地址
{
printf("%d\t", p->value);
}
当要搜索一个链表内的数字,便可使用遍历去匹配这个数字,再进行其他操作
链表的删除
利用链表的搜索,找到要操作的数字,再继续删除
如何删除呢?
-
将删除结点前的next指向后一个结点的首地址
-
定义两个指针,初始化一个为NULL,利用一个指针p指向要删除的结点的首地址;当搜索到的结点为目标结点,则让q的next等于p的next,即指向目标结点的下一个,再free掉目标结点
node *p, *q;
scanf("%d", &number);
for(q = NULL,p = list.head; p; p = p->next)//相应设置
{
if(p->value == number)//如果为目标结点,则进入循环,否则p指向下一个,for循环的结束操作
{
if( q )//要先保证q不为NULL,即第一个结点刚刚好是目标结点时,令它单独操作,因为->左边有NULL,编译器会识别为error
{
q->next = p->next;//令目标节点的next指向目标节点下一个首地址
}
else
{
list.head = p->next;//当第一个结点刚刚好是目标结点时,转移链表首地址,以方便下面free操作
}
free(p);
break;
}
}
链表的清除
node *p, *q;
for(p = list.head; p; p = q)//从第一个节点开始;p不为NULL,即不为最后一个节点;操作结束后让p变成下一个节点首地址继续操作
{
q = p->next;//保留下一个节点首地址
free(p);//找一个free一个
}