介绍
线性表是链式结构也称作链表,那什么是链表?
你可以把它想象成一串项链,数据就像是项链上的珠子,我们要做的就是用线把这些珠子串起来形成“链表”。当然,这样形容十分不准确,链表可比“项链”高级多了。
正文
准备操作
头文件
首先是头文件
#include <stdio.h>
#include <stdlib.h>
节点
然后就是构建那些存放数据的”珠子“——节点。
这些“珠子”在内存里可不止占一份存储空间,我们可以将它划分为两大空间——数据域(value)和指针域(next)(域就是存储空间的意思)。
顾名思义数据域就是放我们需要存储的数据的地方,那么指针于的指针又是指向谁的呢?
它是指向链表的下一个“珠子”。
typedef struct _node{
int value;
struct _node next;
} Node;
//这里我建了一个特殊的“珠子”,我们称它为表头,当然你也可以建一个没有表头的链表;
typedef struct {
Node head;
}List;
正式操作
建立链表
然后我们要思考如何去找一根线将这些“珠子”串起来,
其实线我们早就找到了就是指向下一个“珠子”的指针;
建立一个函数,用来组装链表;
void min(int n,List* plist){
//输入-1后结束读取操作
if(n!=-1){
Node *p=(Node*)malloc(sizeof(Node));//这里给“珠子”赋予了一片空间
p->value = n;//将输入的数据放到“珠子”里
p->next =NULL;//将指针指空,毕竟你串入的“珠子”是最后一个“珠子”
Node *last=plist->head;//last应表示最后一个“珠子”通过下方遍历的方式
//将它“滑到”原来的链表末尾(一开始只有一个空的表头)
if(last){
while(last->next ){
last=last->next ;
}
last->next =p;//如果last滑到末尾,则像一只手一样将最后的“珠子”的线头和下一个珠子相连
//(也可以理解为last像鬼一样附身到最后一个“珠子”操纵它与下一个珠子相连)
}else{
plist->head =p;//如果表头为空则将第一个“珠子”设为表头
}
}
}
打印链表
打印表头可以让你看见输入链表的数据是否正确
void print(List list){
Node *p;
for(p=list.head ;p;p=p->next){//通过指针的方式实现相连的“珠子”间移动,
//这里的p有点像上面的last
printf("%d",p->value);
}
}
删除操作
在链表中我们可以随心所欲的删除任意一个数据,这就是它的高级之处了
void cut(int n,List list){
/*遍历链表寻找目标,p是寻找,判断的媒介,
q用来记录p的上一个“珠子”,去掉目标后使其与目标的下一“珠子”相连,
防止链表断了。*/
for(Node* p=list.head,*q=NULL;p;q=p,p=p->next){
if(p->value == n){
q->next = p->next ;//连接
free(p);//释放目标的空间(删除目标)
break;//退出循环
}
}
}
插入操作
void add(int n,int item,List list){
Node* q=(Node*)malloc(sizeof(Node));//建立节点存放数据
q->value=item;
for(Node* p=list.head;p;p=p->next){
if(p->value == n){
q->next = p->next ;
p->next = q;
break;
}
}
}
}
主体
int main()
{
int n=0;
int item;
List list;
list.head=NULL;
while(n!=-1){
scanf("%d",&n);
min(n,&list);//输入数据
}
print(list);
printf("\n");
scanf("%d",&n);
cut(n,list);//删除数据
print(list);
printf("\n");
scanf("%d",&n);
scanf("%d",&item);
add(n,item,list);//插入数据
print(list);
printf("\n");
return 0;
}
总结
这里我只是简单的列了几个链表的基本操作,在此基础上你可以在节点中添加序号,使操作更加方便。也可以在节点中再添加一个指向前面的指针,形成双向指针,还可以在节点中再添加一个指向下一节点的指针,形成二叉树……总之链表是灵活的。它为编程实现各种可能。