今天学习了翁恺老师《C语言程序设计》14.2课 链表,这是对上一课可变数组的优化。
何为链表?
就是在每一个数据的后方放置一个指针,链接下一个数据…每个数据和指针合称为节点(最后一个节点的指针为NULL)当需要加入新数据时,只需新建一个节点,并将已有的最后一个节点的指针连接到新的节点上。
这是基础存数据的代码
#include <stdio.h>
#include <stdlib.h>
#include "node.h"
typedef struct _node{
int value;
struct _node *next;
}Node;
int main()
{
Node *head=NULL;
int number;
do{
scanf("%d",&number);
if(number!=-1){
//add to linked-list
Node *p=(Node*)malloc(sizeof(Node));//申请一块内存空间
p->value=number;
p->next=NULL;
// find the last
Node *last=head;//首先要保证head有内容
if(last){
while(last->next){
last=last->next;
}
last->next=p;
}else{
head=p;
}
}
}while(number!=-1);
return 0;
}
下一步,我们要将加入数据的部分分装成一个函数。但是仅仅复制并且稍加修改就可以了吗?答案是否定的。就如以前的swap函数一样,如果不传入指针(地址),是无法进行交交换的。这里也一样,head无法被改变,因此可以用指针的指针或者全局变量,但是这里给出一种新方法。(实际上等价于指针的指针,但是这样操作有更大的作用)
typedef struct _list{
Node* head;
}List;
void add(List *list,int number)
{
//将number存入p中
Node *p=(Node*)malloc(sizeof(Node));
p->value=number;
p->next=NULL;
//find the last
Node *last=list->head;
if(last){
while(last->next){
last=last->next;
}
last->next=p;
}else
list->head=p;
}
新加入一个list有什么用处吗?和单纯的利用指针的指针有什么不同呢?注意到每一次加入元素时,都要遍历整个链表,这样就显得很不方便。我们是不是可以在每次结束时加上一个记号tail,下次从tail往后添加元素就可以了?
改进:
结构体加入一个tail
typedef struct _list{
Node *head;
Node *tail;
}List;
void add(List *list,int number)
{
Node * last = list->head;
Node* p = (Node*)malloc(sizeof(Node));//问题1:为什么是指针,为什么开辟
p->value = number;
p->next = NULL;
last = list->tail;
if(last)
{
last->next = p;
list->tail = p;
}
else
{
list->tail = p;
list->head = p;//这句话必须要加
}
}
至此,一个基本链表就完成了。但是还缺少删除数据,清除链表等操作。