举个例子啊!
C语言的连续存储(像数组,动态划分的连续空间)就像大学宿舍,一个学院的同学全都放到一个宿舍楼,里面一个宿舍挨着一个宿舍,找你们院的同学,你可以一个一个寝室挨着找
但链表是 一个学院的同学放到不同宿舍楼里面,但你找人的时候,找完一个宿舍,没找到,这个宿舍中的同学告诉你下一个咱们院的宿舍在那栋楼(千万别挨着着找,找到黑也找不到),然后你就找下一个宿舍。那这个过程中是不是得有一个宿舍信息代表这个宿舍,那这个信息就相当于一个指针,指向下一个单元。
/**
线性链表的回炉再造
:一个链表包含一个头结点,和若干个中间结点,头结点记录整个链表的信息
就像火车,火车头里的记录本知道 后面跟了多少个车厢
*/
#include<stdio.h>
#include<stdlib.h>
#define true 1
#define false 0
typedef int status;
typedef struct LNode{
int num;
struct LNode * next;//结点类型
}LNode;
typedef LNode* link;
typedef struct{
link head,tail;//链表信息结点,包含着链表的头部和尾部d
int len ; //链表的长度
}LinkList;
/*
本书完全按照《数据结构》严蔚敏 的guidance思路进行练习
**/
status MakeNode(link &p,int elem)//结点构造函数,返回一个结点,使用起别名的参数传递
{
if((p=(link)malloc(1*sizeof(LNode)))!=NULL)
{
p->num=elem;
p->next=NULL;
return true;
}
else
return false;
}
//添加结点,需要传入头指针,新建结点,I是正序添加 II是倒序添加
status addNodeI(LinkList &L,link n)
{
if((L.head)==NULL)
{
L.head = n;
L.tail = n;
L.len ++ ;
}
else
{
L.tail->next = n;
n->next=NULL;
L.tail=n;
L.len ++;
}
}
//逆序添加结点
status addNodeII(LinkList &L,link n)
{
if((L.head)==NULL)
{
L.head = n;
L.tail = n;
L.len ++ ;
}
else
{
n->next=L.head;
L.head=n;
L.len++;
}
}
//查找第n个结点
link GetElem_n(LinkList L,int n)
{
link p;
p=L.head;
int j=1;//j用来记录当前的位置
if(n>L.len)
{
printf("超出链表长度");
return 0;
}
while(j<n)
{
p=p->next;
}
return p;
}
//按内容删除特定结点,删除的时候要注意如果是头部和尾部的特殊情况
status delete_content(LinkList & L,int target)
{
link p=L.head;
link q=L.head;
if(!p)
{
printf("列表长度为零");
return 0;}
if(p->num==target)
{
L.head=p->next;
L.len--;
return 1;
}
p=p->next;
while(p)
{
if(p->num==target)
break;
p=p->next;
q=q->next;
}
if(p)
{
q->next=p->next;
free(p);
return 1;
}
return 0;
}
//顺序输出结点
void OutPut(LinkList L)
{
if(L.len==0)
{
printf("链表为空");
}
else
{
link p;
p=L.head;
while(p!=NULL)
{
printf("%d ",p->num);
p=p->next;
}
printf("输出完整");
}
}
int main()
{
LinkList L;//输入10个数据
L.len=0;
link y;
MakeNode(y,6);
addNodeI(L,y);
MakeNode(y,45);
addNodeI(L,y);
MakeNode(y,8);
addNodeI(L,y);
MakeNode(y,2);
addNodeI(L,y);
OutPut(L);
delete_content(L,45);
OutPut(L);
free(L.head) ;
}