什么是单链表
链表属于基本的数据类型,与顺序表同属于线性表。
单链表为链表中基本的数据类型。其数据节点在c语言中用结构体实现可以用typedef来给变量起别名。
typedef int ElementType;
typedef struct A
{
ElementType data;
struct A* next;
} A, * B;
开始时要建立一个链表
B creatdate()//创建链表
{
int length;//节点的长度
int data;//用来给每个节点的数据域赋值
B Head = (B)malloc(sizeof(A));
if(Head == NULL)
{
printf("分配空间失败,请重新分配");
exit(-1);//如果分配失败直接结束程序
}
B wei = Head;
wei->next = NULL;
printf("请输入节点个数");
scanf("%d",&length);
int i = 0;
for(;i<length;i++)
{
printf("请输入第%d节点数值",i+1);
scanf("%d",&data);
B wNew = (B)malloc(sizeof(A));
if(wNew == NULL)
{
printf("分配空间失败,请重新分配");
exit(-1);
}//真正有用的节点
wNew->data = data;
wei->next = wNew;//wNew成为了wei的成员,wNew指向wei
wNew->next = NULL;
wei = wNew;
}
printf("创建链表成功");
return Head;
}
为尾插法
具体思路为
head为头指针里面的data成员不储存数值,head的next成员指向下一个节点,再设置两个指针一个叫tail(尾指针)指向一个链表的末尾,另一个叫wNew(指向新节点的指针),需要注意的是开始的时候只有一个节点——头节点,所以tail也指向head(头节点)(请注意,在上一段段代码中尾指针的名字叫wei而不是tail)
B wei = Head; //head头节点开始时候也是尾节点
然后用创建节点
B wNew = (B)malloc(sizeof(A));//给wNew所指向的地址分配节点所需的字节
此时,还没有和链表上的节点链接,且里面没有有效值
wNew->data = data;
wei->next = wNew;//wNew成为了wei的成员,wNew指向wei
wNew->next = NULL;
wei = wNew;
第一行代码将数据存入节点中,第二行代码两个节点链接起来,第三行将新节点的下一个设置为空,最后wNew指针当前指向的节点在最后面,所以成为了尾指针所指的节点结果如下
完成后有了初始链表
还要有一个链表的显示函数
int readlist(B Head)//链表的显示
{
B read = Head->next;
if(read == NULL)
{
return 0;
}
printf("链表内容为");
while(read != NULL)
{
printf("%d ",read->data);
read = read->next;
}
return 1;
}
用指针指向每一个节点,如果当前为空表则返回0。
链表的增删改查
以链表的增加为例子
B addlist(B head,int num)//链表的增加
{
//不能通过直接修改原来的链表元素来增加链表节点,而是要链接才行
B tail = head;
while(tail->next)
{
tail = tail->next;
}
int i = 0;
for(;i<num;i++)
{
B pnew=(B)malloc(sizeof(A));
printf("请输入加入的第%d个节点的值:",i+1);
int data;
scanf("%d",&data);
pnew->data = data;
if(pnew == NULL)
{
printf("分配节点失败");
exit(-1);
}
pnew->next = tail->next;
tail->next = pnew;
tail = pnew;
}
return head;
}
需要注意的是,链表节点的增加和链表的建立很相似,注意的一点是新数据要新增加的节点来储存否则会出错,系统读不出新的节点如
B tail=(B)malloc(sizeof(A));
printf("请输入加入的第%d个节点的值:",i+1);
int data;
scanf("%d",&data);
tail->data = data;
if(tail == NULL)
{
printf("分配节点失败");
exit(-1);
}
tail->next = NULL;
其余删改查函数类似的函数,就不一一举例了
附源代码
#include <stdio.h>
#include <malloc.h>
#include <windows.h>
//单链表的增删改查
typedef int ElementType;
typedef struct A
{
ElementType data;
struct A* next;
} A, * B;
B creatdate()//创建链表
{
int length;
int data;
B Head = (B)malloc(sizeof(A));
if(Head == NULL)
{
printf("分配空间失败,请重新分配");
exit(-1);
}
B wei = Head;
wei->next = NULL;
printf("请输入节点个数");
scanf("%d",&length);
int i = 0;
for(;i<length;i++)
{
printf("请输入第%d节点数值",i+1);
scanf("%d",&data);
B wNew = (B)malloc(sizeof(A));
if(wNew == NULL)
{
printf("分配空间失败,请重新分配");
exit(-1);
}//真正有用的节点
wNew->data = data;
wei->next = wNew;//wNew成为了wei的成员,wNew指向wei
wNew->next = NULL;
wei = wNew;
}
printf("创建链表成功");
return Head;
}
int readlist(B Head)//链表的显示
{
B read = Head->next;
if(read == NULL)
{
return 0;
}
printf("链表内容为");
while(read != NULL)
{
printf("%d ",read->data);
read = read->next;
}
return 1;
}
B addlist(B head,int num)//链表的增加
{
//不能通过直接修改原来的链表元素来增加链表节点,而是要链接才行
B tail = head;
while(tail->next)
{
tail = tail->next;
}
int i = 0;
for(;i<num;i++)
{
B pnew=(B)malloc(sizeof(A));
printf("请输入加入的第%d个节点的值:",i+1);
int data;
scanf("%d",&data);
pnew->data = data;
if(pnew == NULL)
{
printf("分配节点失败");
exit(-1);
}
pnew->next = tail->next;
tail->next = pnew;
tail = pnew;
}
return head;
}
B deletelist(B head,int num)//根据值删除一个节点
{
B tail = head;
while(tail->next&&tail->next->data != num)
{
//两种情况终止循环1.找到了节点2.遍历了节点
tail = tail->next;
}
if(tail->next->data != num)
{
printf("当前链表内无查询数据");
return head;
}
B delet = tail->next;
B now = tail;
now->next = delet->next;
free(delet);
return head;
}
B changelist(B head,int num1,int num2)
{
B tail = head;
while(tail&&tail->data != num1)
{
tail =tail->next;
}
if(tail == NULL)
{
printf("未查到修改节点");
return head;
}
else
{
tail->data = num2;
}
return head;
}
B searchlist(B head,int num)
{
B tail = head;
int i = 0;
while(i!=num&&tail)
{
tail = tail->next;
i++;
}
if(!tail)
{
printf("当前链表内无没有第%d个节点",num);
return head;
}
else
{
printf("第%d个节点的值为%d\n",i,tail->data);
}
return head;
}
int length(B Head)//链表的长度的查询
{
B read = Head->next;
if(read == NULL)
{
return 0;
}
int i = 0;
while(read != NULL)
{
read = read->next;
i++;
}
printf("链表的长度为%d\n",i);
return i;
}
int main()
{
B M = creatdate();
printf("是否增添节点输入1否则输入0\n");
int choo = 0;
scanf("%d",&choo);
if(choo==1)
{
printf("请输入增加节点的个数");
scanf("%d",&choo);
addlist(M,choo);
readlist(M);
}
printf("是否删除节点输入1否则输入0\n");
choo = 0;
scanf("%d",&choo);
if(choo==1)
{
printf("请输入删除节点的数据");
scanf("%d",&choo);
deletelist(M,choo);
readlist(M);
}
printf("是否修改某个节点输入1否则输入0\n");
choo = 0;
scanf("%d",&choo);
if(choo==1)
{
printf("请输入要修改节点的数据\n");
int change;
scanf("%d",&change);
printf("请输入修改后节点的数据\n");
scanf("%d",&choo);
changelist(M,change,choo);
readlist(M);
}
printf("是否查找某个节点输入1否则输入0\n");
choo = 0;
scanf("%d",&choo);
if(choo==1)
{
printf("请输入要查找的节点的序号\n");
int change;
scanf("%d",&change);
searchlist(M,change);
}
length(M);
readlist(M);
}
无头节点无循环的单链表源代码:https://blog.csdn.net/cat_want_fly/article/details/86434835
有头节点的双向循环链表源代码:https://blog.csdn.net/cat_want_fly/article/details/86481703