1.链表与数组的区别: 谈到链表与数组的区别,可以从几个不同的角度来谈, 首先从逻辑结构
上说,两者都是数据结构的一种,但存在区别, 数组是申请的一块连续的内存空间,并且是在
编译阶段就要确定空间大小的,同时在运行阶段是不允许改变的,所以它不能够随着需要的改
变而增加或减少空间大小,所以当数据量大的时候,有可能超出了已申请好的数组上限,产生
数据越界,或者是数据量很小,对于没有使用的数组空间,造成内存浪费。 链表则是动态申请
的内存空间,并不像数组一样需要事先申请好大小,链表是现用现申请就OK,根据需求动态的
申请或删除内存空间,对于的是增加或删除数据,所以比数组要灵活。 再从物理存储即内存分
配上分析, 数组是连续的内存,对于访问数据,可以通过下标直接读取,时间复杂度为O(1),
而添加删除数据就比较麻烦,需要移动操作数所在位置后的所有数据,时间复杂度为O(N)。
链表是物理上非连续的内存空间,对于访问数据,需要从头便利整个链表直到找到要访问的数
据,没有数组有效,但是在添加和删除数据方面,只需要知道操作位置的指针,很方便可以实
现增删,教数组比较灵活有效率。 所以综合以上,对于快速访问数据,不经常有添加删除操作
的时候选择数组实现,而对于经常添加删除数据,对于访问没有很高要求的时候选择链表。
2.链表的创建以及链表的静态添加:
来看看一个链表是怎么生成的以及它的静态添加代码:
#include<stdio.h>
struct Link
{
int a;
char c;
struct Link *next;//在结构体中加入一个指针,为生成一个链表做准备
};
int main()
{
struct Link t1 = {100,'a',NULL};
//静态给两个结构体赋值
struct Link t2 = {200,'b',NULL};
t1.next = &t2;//将结构体1中的指针指向结构体2,这样一个简易链表就产生了
printf("use t1 go to input t2\n");
printf("t1:%d %c t2:%d %c\n",t1.a,t1.c,(t1.next)->a,(t1.next)->c);
return 0;
}

可以看到,通过结构体t1输出了t2中的值,这就是一个链表,将结构体t1和t2关联了起来 然后我们再来看看链表的遍历:
#include<stdio.h>
struct Link
{
int a;
char c;
struct Link *next;
};
void printLink(struct Link *p)//不直接用t1来访问t2,而是通过指针的移动来遍历链表,从而输出两个结构体中的数据
{
while(p != NULL){
printf("%d %c\n",p->a,p->c);
p = p->next;
}
}
int main()
{
struct Link t1 = {100,'a',NULL};
struct Link t2 = {200,'b',NULL};
t1.next = &t2;
printLink(&t1);
return 0;
}

通过这种方式也能实现对链表中数据的访问,毫无疑问,这种方式更为的简洁,尤其是当链表中元素很多的时候,采用这种遍历的方法尤为的重要。
3链表的动态添加(头插法): 静态添加显得有些呆滞,大部分时候我们还是需要动态输入数据,因为这里来介绍一种动态添加的方法即头插法.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Link
{
int a;
char c;
struct Link *next;
};
void printLink(struct Link *p)//将头插法后的链表中的数据以遍历的方式打印出来
{
while(p != NULL){
printf("%d %c\n",p->a,p->c);
p = p->next;
}
}
struct Link* insertFromHead(struct Link *p)//封装的头插法函数
{
struct Link *new;
while(1){
new = (struct Link*)malloc(sizeof(struct Link));
printf("plaese input number and letter\n");
scanf("%d",&new->a);
getchar();//吸收scanf中的回车
scanf("%c",&new->c);
if(new->a<=0){
printf("You input a error data\n");
return p;
} //以用户输入小于零的数来终止头插法,大家也可以根据自己的习惯来设计
if(p == NULL){
p = new;
}else{
new->next = p;
p = new;
}
}
return p;
}
int main()
{
struct Link *head = NULL;
head = insertFromHead(head);
printLink(head);
return 0;
}

可以看到当我输入0的时候,程序自动终止了,并且先输入的数据排在链表的后面,这也体现了头插法的特点,好了,关于链表的介绍就到这里了,希望能对学习链表的你们有所帮助。