有头单向链表操作思想
1、链表插入:
解题思想:
1、先遍历找到要插入节点的前一个节点,假设这个节点为A;A的下一个节点为B;
将C插入A与B之间;
2、先让C的指针域指向B;
3、再让A的指针域指向C;
(注意:顺序不可以调换)
2、链表删除:
解题思想:
1、先遍历找到要删除节点的前一个节点,假设为A;
2、找一个临时指针指向要删除的节点;
3、将A的指针域指向删除节点的下一个节点;
3、转置链表:
解题思想:
1、将头节点与当前链表断开,断开前保存头节点的下一个节点,保证后面链表能找得到,定义一个q保存头节点的下一个节点,断开后前面相当于一个有头的空链表,后面是一个无头的单向链表
2、遍历无头链表的所有节点,将每一个节点当做新节点头插到有头空链表中(每次插入到头节点的下一个节点位置)
void ReverseLinkList(link_node_t *p)
4、链表清空:
.h文件
#ifndef __LIANBIAO_H__
#define __LIANBIAO_H__
#include <stdio.h>//在自己的.h文件中包含表准头文件
#include <stdlib.h>//需要用到malloc函数
#define bian int//将整形定义成宏
typedef struct lianbiao
{
bian data;//存放数据
struct lianbiao* next;//存放下一位的地址
}lianshu,*lianzhi;
//创建一个空表
lianshu *kongbiao();
//插入一个链式数据
int chalu(lianshu *p,int post,bian data);
//便利单项链表
void zhanshi(lianshu *p);
//求单项链表的长度
int qiuchang(lianshu *p);
//删除单项链表
int shanchu(lianshu *p,int post);
//转至链表
int zhuanzhi(lianshu *p);
//修改指定位置的数据
int xiugai(lianzhi p,int post,bian data);
//找到数据出现的位置
int zhao(lianzhi p, bian data);
//删除指定的数据
int shanzhi(lianzhi p,bian data);
//判断是否为空
int pankong(lianzhi p);
//清空数据链表
void qingkong(lianzhi p);
#endif
. c文件
#include "lianbiao.h"
//创建一个空表
lianshu *kongbiao()
{
lianshu *h = (lianzhi)malloc(sizeof(lianshu));//定义一个结构体指针,开辟一个堆区空间,做为表头
if(NULL == h)//如果指针指向空
{
printf("malloc head node filed\n");
return NULL;//开辟空间失败,返回空
}
h->next = NULL;//开辟成功,将结构体指针中的成员next指针指向空
return h;//返回h的地址,传值
}
//插入一个链式数据
int chalu(lianshu *p,int post,bian data)//传值:指向链表的指针,要插入的位置,要插入的数据
{
if(post < 0 || post > qiuchang(p))//如果位置小于0,或者位置大于次函数返回的值,函数判断链表的大小
{
printf("输入的位置有问题\n");
return -1;//返回-1
}
lianshu *pnew = (lianzhi)malloc(sizeof(lianshu));//定义一个结构体指针变量pnew,开僻一个新的堆区空间
if(NULL == pnew)//判断是否开辟成功
{
printf("malloc pnew node filed\n");
return -1;
}
//开辟成功初始化结构体的成员变量
pnew->data=data;//data变量赋值为data
pnew->next=NULL;//结构体指针pnew变量的成员next结构体指针指向空
int i;
for(i=0;i<post;i++)//从零开始,到达要插入对象的前一位(<)
{
p = p->next;//将指针p的值改为链表的下一为(指针p往后移动)
}
pnew->next = p->next;//将指针p中的指针变量next里存的地址付给pnew指针的next的指针变量
p->next = pnew;//将指针pnew指向的地址赋值给p指针的next指针成员
return 0;
}
//便利单项链表
void zhanshi(lianshu *p)
{
while(p->next != NULL)//当指针p指向的结构体成员next指针的指向不是空时
{
p = p->next;
printf("%d ",p->data);
}
printf("\n");
}
//删除单项链表
int shanchu(lianshu *p,int post)//传值:指向链表的指针,要删除的位置
{
if(post < 0 || post >= qiuchang(p))//判断位置输入的是否合理
{
printf("输入的位置有问题\n");
return -1;
}
int i;
for(i=0;i<post;i++)//找到要删除的前一位
{
p = p->next;
}
lianzhi pdel = p->next;//定义一个新的结构体指针,指向要删除的节点
p->next = pdel->next;//将指针p指向的结构体中next指针指向指针pdel指向的结构体中next中存的地址(pdel->next中存的是下一位的首地址)
free(pdel);//放空没用的指针
pdel = NULL;//将没用的指针指向空
return 0;
}
//求单项链表的长度
int qiuchang(lianshu *p)
{
int len = 0;
while(p->next != NULL)
{
p = p->next;
len++;
}
return len;
}
//转至链表
int zhuanzhi(lianshu *p)
{
lianzhi q = p->next;
lianzhi temp = NULL;//用来存放q的下一位地址
//将头文件和后面的链表断开
p->next = NULL;
//便利无头单项链表
while(q != NULL)//当p不指向空时:如果是最后一位,p->next是空,会把空置传给temp,循环完成后结束
{ //但不可以直接p->next != NULL 这样判断不会执行最后一位
//用temp临时记录一下q的下一个节点
temp = q->next;
//插入动作
q->next = p->next;
p->next = q;
q = temp;//将下一个节点的位置付给q,开始下一轮循环
}
return 0;
}
//修改指定位置的数据
int xiugai(lianzhi p,int post,bian data)
{
if(post < 0 || post > qiuchang(p))
{
printf("输入的位置有误\n");
return -1;
}
int i;
for(i = 0;i<post;i++)
p = p->next;
p->data = data;
return 0;
}
//找到数据出现的位置
int zhao(lianzhi p, bian data)
{
int le=0;
while(p->next != NULL)
{
p = p->next;
if(p->data == data)
{
printf("%d\n",le);
return le;
}
le++;
}
return -1;
}
//删除指定的数据
int shanzhi(lianzhi p,bian data)
{
lianzhi pdel =NULL;
if(pankong(p))
{
printf("错误\n");
return -1;
}
while(p->next != NULL)
{
if(p->next->data == data)//指针p指向的下一个地址的数据等于要删除的数据
{
pdel = p->next;//指针pdel指向p指针指向的下一个地址
p->next = pdel->next;//吧pdel指向的下一个地址付给指针p的next
free(pdel);//放空对空间
pdel = NULL;//指针pedl指向空
}
else
{
p = p->next;//指针p往后移
}
}
return 0;
}
//判断是否为空
int pankong(lianzhi p)
{
return p->next == NULL;
}
//清空数据链表
void qingkong(lianzhi p)
{
lianzhi pdel = NULL;
while(p->next != NULL)
{
pdel = p->next;//将p的下一位地址传给pdel
p->next = pdel->next;//将pdel的下一位地址传给p的next
free(pdel);//放空pdel
pdel = NULL;//让pdel指向空
}
}
main.c文件可以根据自己的需要调用函数