##C语言 链表
单向链表的定义(Linked list):线性表的链式存储结构
链表的组成:一系列的节点
节点的组成: 1、数据域(任意类型)
2、指针域(指针的类型为该节点的类型)
头节点:指向第一个节点的指针(头节点没有前驱节点)
尾节点:节点的指针域为NULL(尾节点没有后继节点)
注释:可以通过第一个节点的指针域存储第二个节点的地址,第二个节点的指针域存储第三个节点的地址…的方法将散列的节点连接起来的。
建立一个简单得单向链表得步骤:
第一步:定义节点类型
· typedef struct player{
int number; //数据域用来存放节点信息可以有定义多个不同类型的数据信息
char name[20];
struct player*next; //指针域必须是与结构体同类型的指针用来存放下一个节点的地址
}Player
第二步:创建节点
第三步:将单个节点链起来(使每个节点得指针域存储后继节点得地址)
第四步:确定头节点
注:此时pt既是头节点也是尾节点
第五步:确定尾节点
1、创建节点
int main()
{
int sum;
printf(“请输入玩家个数:”);
scanf("%d",&sum); //用户输入节点个数
Playerhead=NULL;
return 0;
}
Playergame(int sum)
{
int i;
Playerhead=NULL,pt,pre; //定义头节点,过度节点,尾节点
for(i=0;i<sum;i++){ //用循环的方式创建sum个节点
pt=(Player)malloc(sizeof(Player)); //向系统空间为过度节点申请一个Player结构类型的空间
if(pt!=NULL){ //判断是否成功的向系统空间申请了内存
scanf("%d%s",&pt->number,pt->name); //用户输入节点的数据域(赋值)
if(headNULL){ //headNULL时说明链表是空链表进行头节点的处理 也可将此条语句改为if(i==0)
head=pt; //让头节点的地址指向过度节点的地址
pre=pt; //此时pt既是头节点也是尾节点
}
else { //执行else语句的说明链表已经创建好了头节点
pre->next=pt; //将尾节点与过度节点连接起来
pre=pt; //将尾节点的地址指向过度节点的地址(此时pt既是过度节点也是尾节点)
}
}
else{
printf(“Failed.\n”);
exit(0);
}
}
pre->next=NULL; //让尾节点的指针域为空表明链表结束
return head;
}
2、 查找尾节点
注:尾节点得指针域为空只要循环判断节点的指针域是否为空
PlayerFindlast(Playerhead)
{
Player*lastnode=head; //定义尾节点从头开始查找
while(lastnode->next!=NULL){ //最后一个人节点信息的指针域为NULL
lastnode=lastnode->next;
}
return lastnode;
}
3、查找链表中任意节点的信息
PlayerFind(Playerhead,int sum)
{
int a=1;
int n;
Player*node=head;
printf(“请输入需要查找节链表节点的序号:”);
scanf("%d",&n); //用户输入链表节点的序号(也就是从链表头开始的第几个节点)
while(n<=sum&&node!=NULL){ //只要用户输入的序号小于链表的总结点数并且node不为尾节点的
if(a==n){ //只要a等于n说明找到了只需要返回当前节点信息即可
return node;
}
else{
node=node->next //指向下一个节点信息;
a++;
}
}
4、在链表尾部插入新的的节点
PlayerInsert(Playerhead){
Playerlastnode=Findlast(head);//调用函数求链表的尾节点
Playerpt=(Player*)malloc(sizeof(Player));//给待插入的节点申请内存空间
if(pt!=NULL){ //判断内存空间申请是否成功
printf(“请输入节点信息:\n”);
scanf("%d%s",&pt->number,pt->name); //用户输入待插入的节点信息
lastnode->next=pt;//链表尾节点的指针域存放新插入节点的地址
pt->next=NULL; //让新插入的节点成为链表的为节点
return head;
}
}
5、在任意位置插入节点
注释:为防止造成链表环路必须先处理待插入节点与后继节点的位置再处理与前驱节点的位置
先处理:pt->next=pr->next
后处理:pr->next=pt;
Playerinsert(Playerhead,int index){
Playerpr=Find(head,index); //调用Find函数求出新插入节点的位置
Playerpt=(Player*)malloc(sizeof(Player));//向系统空间给待插入节点申请内存
if(pt!=NULL){
printf(“请输入节点信息:\n”);
scanf("%d%s",&pt->number,pt->name);//用户输入节点信息
pt->next=pr->next;//待插入节点的指针域存储待插入节点的后继节点的地址(代插入节点的后继节点的地址原先在pt的前驱节点的指针域中存储)
pr->next=pt;//pt的前驱节点的指针域存储pt节点的地址
}
return head;
}
6、删除节点信息
PlayerDelete(Playerhead,int index)
{
int x;
printf(“请输入删除节点序号”);
scanf("%d",&x);
index=x;
Playerpr=Find(head,index-1);//找到用户删除节点的前一个节点的信息并且存储在pr中
Playerpt=Find(head,index);//找到需要删除的节点
if(pt!=NULL){
pr->next=pt->next;
free(pt);//返回已删除的节点的内存
return head;
}
}
}
7、输出链表信息
void print(Playerhead,Playerlastnode,Player*node)
{
//遍历输出链表信息
while(head!=NULL){
printf("%d,%s\n",head->number,head->name);
head=head->next;//输出完之后指向下一个节点
}
//输出尾节点信息
printf(“the last node number is %d name is %s\n”,lastnode->number,lastnode->name);
//输出第n个节点信息
printf(“the number is %d name is %s\n”,node->number,node->name);
return;
}
完整的代码:
#include<stdio.h>
#include<stdlib.h>
//定义节点类型
typedef struct player{
int number; //数据域用来存放节点信息可以有定义多个不同类型的数据信息
char name[20];
struct player*next; //指针域必须是与结构体同类型的指针用来存放下一个节点的地址
}Player;
Player*game(int sum); //定义game函数 函数返回类型为结构体类型的指针需要一个sum参数来表示有多少个节点
Player*Findlast(Player*head); //定义查找最后节点信息函数
Player*Insert(Player*head); //定义插入函数
Player*Find(Player*head,int index); //定义查找第n个节点信息
Player*insert(Player*head,int index); //定义在任意地方插入函数
Player*Delete(Player*head,int index); //定义删除节点信息函数
void print(Player*head,Player*lastnode,Player*node); //定义输出函数
int main()
{
int sum,index;
printf("请输入玩家个数:");
scanf("%d",&sum); //用户输入节点个数
Player*head=NULL,*lastnode,*node;
head=game(sum);
lastnode=Findlast(head);
head=Insert(head);
head=insert(head,index);
node=Find(head,index);
head=Delete(head,index);
print(head,lastnode,node);
return 0;
}
Player*game(int sum)
{
int i;
Player*head=NULL,*pt,*pre; //定义头节点,过度节点,尾节点
for(i=0;i<sum;i++){ //用循环的方式创建sum个节点
pt=(Player*)malloc(sizeof(Player)); //向系统空间为过度节点申请一个Player结构类型的空间
if(pt!=NULL){ //判断是否成功的向系统空间申请了内存
scanf("%d%s",&pt->number,pt->name); //用户输入节点的数据域(赋值)
if(head==NULL){ //head==NULL时说明链表是空链表进行头节点的处理 也可将此条语句改为if(i==0)
head=pt; //让头节点的地址指向过度节点的地址
pre=pt; //此时pt既是头节点也是尾节点
}
else { //执行else语句的说明链表已经创建好了头节点
pre->next=pt; //将尾节点与过度节点连接起来
pre=pt; //将尾节点的地址指向过度节点的地址(此时pt既是过度节点也是为节点)
}
}
else{
printf("Failed.\n");
exit(0);
}
}
pre->next=NULL; //让尾节点的指针域为空表明链表结束
return head;
}
//查找最后一个节点
Player*Findlast(Player*head)
{
Player*lastnode=head; //定义尾节点从头开始查找
while(lastnode->next!=NULL){ //最后一个人节点信息的指针域为NULL
lastnode=lastnode->next;
}
return lastnode;
}
//在链表的尾部插入新的节点信息
Player*Insert(Player*head){
Player*lastnode=Findlast(head);//调用函数求链表的尾节点
Player*pt=(Player*)malloc(sizeof(Player));//给待插入的节点申请内存空间
if(pt!=NULL){ //判断内存空间申请是否成功
printf("请输入节点信息:\n");
scanf("%d%s",&pt->number,pt->name); //用户输入待插入的节点信息
lastnode->next=pt;//链表尾节点的指针域存放新插入节点的地址
pt->next=NULL; //让新插入的节点成为链表的为节点
return head;
}
}
//查找第n个节点信息
Player*Find(Player*head,int index)
{
int a=1;
int n;
Player*node=head;
printf("请输入需要查找节链表节点的序号:");
scanf("%d",&n); //用户输入链表节点的序号(也就是从链表头开始的第几个节点)
index=n;
while(a<index&&node!=NULL){ //只要用户输入的序号小于链表的总结点数并且node不为尾节点的
node=node->next;
a++;
}
return node;
}
//在链表任意位置插入一个节点
Player*insert(Player*head,int index){
Player*pr=Find(head,index); //调用Find函数求出新插入节点的位置
Player*pt=(Player*)malloc(sizeof(Player));//向系统空间给待插入节点申请内存
if(pt!=NULL){
printf("请输入节点信息:\n");
scanf("%d%s",&pt->number,pt->name);//用户输入节点信息
pt->next=pr->next;//待插入节点的指针域存储待插入节点的后继节点的地址(代插入节点的后继节点的地址原先在pt的前驱节点的指针域中存储)
pr->next=pt;//pt的前驱节点的指针域存储pt节点的地址
}
return head;
}
//删除节点信息
Player*Delete(Player*head,int index)
{
int x;
printf("请输入删除节点序号");
scanf("%d",&x);
index=x;
Player*pr=Find(head,index-1);//找到用户删除节点的前一个节点的信息并且存储在pr中
Player*pt=Find(head,index);//找到需要删除的节点
if(pt!=NULL){
pr->next=pt->next;
free(pt);//返回已删除的节点的内存
return head;
}
}
//输出节点信息
void print(Player*head,Player*lastnode,Player*node)
{
//遍历输出链表信息
while(head!=NULL){
printf("%d,%s\n",head->number,head->name);
head=head->next;
}
//输出尾节点信息
printf("the last node number is %d name is %s\n",lastnode->number,lastnode->name);
//输出第n个节点信息
printf("the number is %d name is %s\n",node->number,node->name);
return;
}