一、 什么是链表
1、 概念
链表是一种极其常用的数据结构,它通过指针将一片片独立分散的堆内存节点,连接成一个数据链。从而更加合理的运用内存中分散的内存,同时链表也是很多数据结构的基础,比如说链栈的实现,树的实现(红黑树,二叉搜索树,B_树,…)都用到了链表这一基本数据结构。
2、 链表与数组的区别和联系
如图例子所示,同样分配6个空间,数组a分配的是连续的6个空间,而链表则是分配了6个分散的内存空间,这6个空间都是用一个next的指针指着下一个内存的地址。
数组:一次性分配一块连续的存储区域。
优点:随机访问元素效率高
缺点:1) 需要分配一块连续的存储区域(很大区域,有可能分配失败)
2) 删除和插入某个元素效率低
链表:无需一次性分配一块连续的存储区域,只需分配n块节点存储区域,通过指针建立关系。
优点:1) 不需要一块连续的存储区域
2) 删除和插入某个元素效率高
缺点:随机访问元素效率低
二、 链表的类型
1、 单向链表(本章的重点)
2、 双端链表
3、 循环链表
三、 链表的操作
structData
{
int _datax;
int _datay;
};
structNode
{
struct Data d;
struct Node *next;
};
1、 链表增加节点
structNode * create()
{
struct Node *tmp = (struct Node*)malloc(sizeof(struct Node));
tmp->next = NULL;
return tmp;
}
2、 链表插入节点
int insert(struct Data *d, struct Node *phead)
{
if (phead == NULL) return 0;
else
{
struct Node *p = phead;
while (p->next != NULL)
{
p = p->next;
}
p->next = create();
p->next->d =*d;
}
return 1;
}
3、 链表修改节点
structNode *myselect(struct Data *d, struct Node * phead)//查询目标节点位置
{
struct Node *p = phead;
if (phead == NULL) return NULL;
else
{
while (p != NULL )
{
if (p->d._datax== d->_datax && p->d._datay == d->_datay) return p;
p = p->next;
}
}
return NULL;
}
intmodify(struct Node *src, struct Data *d)//修改指定节点
{
if (src == NULL || d == NULL)
return -1;//error
src->d = *d;
return 0;
}
4、 链表删除节点
int del(struct Node * phead, struct Node * dest)
{
if (dest == NULL || phead == NULL)return 0;
else
{
struct Node * p = phead;
struct Node *pnext = phead->next;
while (pnext != NULL&& pnext != dest)
{
p = p->next;
pnext =pnext->next;
}
if (pnext == dest)
{
p->next =pnext->next;
free(pnext);
return 1;
}
else
{
return 0;
}
}
}
5、 链表反转(理解即可)
intrev(struct Node *phead)
{
struct Node *tmp, *first, *second;
first = phead->next;
second = first->next;
while (second != NULL)
{
tmp = second->next;
second->next = first;
first = second;
second = tmp;
}
phead->next->next = NULL;
phead->next = first;
return 1;
}