数据结构之链表 - 教程
链表的概念
是一种物理结构非连续,非顺序的储存结构;素材元素的逻辑顺序是通过链表中的指针链接来搭建。链表也是线性表,逻辑结构一定是线性的。
链表由一个个节点组成。每一个节点由节点数据和下一给节点的指针。
链表的实现
节点的创建
struct jd{
type x;//节点的类型
struct jd*next;//链接下一个节点
}
节点的打印
实现
void dy(fishjd* ps) {
/*printf("%d ", ps->x);//打印当前节点的资料
if (ps->next != NULL) {//如果下一节点不为空
dy(ps->next);//打印下一个节点
}*/第一种采用了递归。
fishjd* pp = ps;//定义一个同类型的指针,指向要打印的链表。
while (pp) {//如果节点不为空则继续执行
printf("%d ", pp->x);
pp = pp->next;//到达下一个节点
}
printf("NULL");第二种;应用循环
}
效果

尾插
实现
fishjd* cj(fishtp x) {//生成一个新节点,节点数据为x。
fishjd* news = (fishjd*)malloc(sizeof(fishjd));
if (news==NULL) {//如果生成失败,退出
printf("fail");
exit(1);
}
fishjd* ps = news;//创建一个新的节点;
ps->x = x;//给节点赋值;
ps->next = NULL;//新节点的下一个节点为空
return ps;//返回新建的节点
}
void wc(fishjd*ps,fishtp sr) {
fishjd* pp =ps;//创建一个新的指针指向链表开头。
while (pp->next) {//遍历到达链表末尾
pp = pp->next;
}
pp->next = cj(sr);//给链表末尾链接新的节点
};
效果

发现不能传NULL
更改代码传址过去
void wc(fishjd**ps,fishtp sr) {//改变为传递链表的地址
if (*ps == NULL) {//若是是空链表
*ps = cj(sr);//直接创建
return;
}
fishjd*pp =*ps;//*ps取消取址
while (pp->next) {
pp = pp->next;
}
pp->next = cj(sr);
};
更改后的效果

头插
效果

实现
void tc(fishjd** ps, fishtp sr) {//给链表头部插入一个新节点
assert(ps);//防止头插的是空链表
fishjd*newjd = cj(sr);//创建一个新节点;
newjd->next = *ps;//让原链表链接到新节点
*ps = newjd;//把链表改成新链表
}
尾删
效果
实现
void ws(fishjd** ps) {//传址
assert(ps&&*ps);
if ((*ps)->next == NULL) {//判断是不是只有一个元素的链表
free(*ps);//释放链表空间
*ps = NULL;//防止野指针的产生
return;
}
fishjd* p1 = *ps;//定义指针一,二指向链表;
fishjd* p2 = *ps;
while (p1->next) {//遍历链表
p2 = p1;//落后指针一,一个节点
p1 = p1->next;//到达下一个节点
}
free(p1);//释放尾节点
p1 = NULL;//防空
p2->next = NULL;//尾节点前的链接断开
}
头删
效果

实现
void ts(fishjd** ps) {
assert(ps && *ps);
fishjd* p1 = (*ps)->next;//创建一个指向第二个节点的指针
free(*ps);//释放第一给节点空间
*ps = p1;//把链表改成从第二节点开始
}
查找节点
效果

实现
fishjd* czjd(fishjd* ps,fishtp zhi) {//查找节点
fishjd* chazhao = ps;//定义节点指针
while (chazhao) {//遍历
if (chazhao->x == zhi) {//判断是不是有这个素材
return chazhao;//有直接返回当前位置
}
chazhao = chazhao->next;
}
return NULL;//找不到返回空;
}
指定节点前插入
效果

实现
void qc(fishjd** ps, fishjd*pos,fishtp zhi) {
第一给节点前就是if (*ps == pos) {//若是
tc(ps, zhi);//直接调用头插
}
else {
assert(ps && *ps && pos);
fishjd* news = cj(zhi);//定义新的节点
fishjd* prev = *ps;//指向链表
while (prev->next!= pos){//到达指定节点前
prev = prev->next;//节点后走
}
news->next = pos;//让新节点链接目标节点
prev->next = news;//把新链表接上
}
}
指定节点后插入
效果

实现
void hc(fishjd* pos, fishtp zhi) {//不得改变整个链表。传值即可
assert( pos);
fishjd* news = cj(zhi);//创建节点
fishjd* prev = pos->next;//链接节点
pos->next = news;
news->next = prev;
}
指定位置删除
效果

实现
void zs(fishjd** ps, fishjd* pos) {
assert(*ps && ps);
if (*ps == pos) {//如果是头节点
ts(ps);//调用头删
}
else {
fishjd* prev = *ps;//定义指针指向链表
while (prev->next != pos) {//遍历链表的指定节点
prev = prev->next;
}
prev->next = pos->next;//把节点剔除
free(pos);//释放
pos = NULL;
}
}
指定节点的下一个节点删除
效果

实现
void zhs(fishjd* pos) {//删除指定节点的下一个节点。
assert(pos && pos->next);
fishjd* shanc=NULL;
shanc = pos->next;//让下一个节点的信息储存到shanc
pos->next = shanc->next;//链接下下给节点
free(shanc);//释放节点
shanc = NULL;
}
销毁链表
效果

实现
void xh(fishjd** ps) {//销毁链表
assert(*ps && ps);
while ((*ps)->next != NULL) {//执行尾删直到剩下一个头节点
zhs(*ps);
}
ts(ps);//
}

浙公网安备 33010602011771号