C语言,单链表实现(不含文件读入信息,单纯手动)

C语言,单链表实现(不含文件读入信息,单纯手动录入信息)
主要以学生ID,姓名和三课成绩进行操作

结构体定义

struct Node
{
  char name[20];     // 学生姓名
  char no[20];      // 学生学号
  float score[3];    // score数组分别存储语文、数学、英语成绩
  float total;       // 总分
  struct Node *next; // 下一个结点的地址
};

创建链表先上代码图

typedef struct Node *pNode; 
//实现链表的创建(根据文件scores.txt读入)、排序、输出、节点查找、插入、删除
pNode create()//信息读入和链表创建 ,假定scores.txt的文件读入姓名-学号-成绩,每个人一行 
{
 //人数就三个,所以长度为三
 pNode pHead=(pNode)malloc(sizeof(struct Node));
 if(NULL==pHead)
 {
  printf("创建失败");
  exit(-1);//检验是否成功 
 }
 else
 {
  pNode pTail=pHead;//头尾节点
  pHead->next=NULL;//头节点为空
  for(i=0;i<3;i++)//长度可以自定义,循环创建 
  {
   pNode p=(pNode)malloc(sizeof(struct Node));
   if(p==NULL)
   {
    printf("创建失败");
    exit(-1);//检验是否成功 
   }
   else
   {
    //文件读入信息
    scanf("%s",p->no);
    scanf("%s",p->name);
    scanf("%f",&(p->score[0]));
    scanf("%f",&(p->score[1]));
    scanf("%f",&(p->score[2]));
    scanf("%f",&(p->total));
    pTail->next=p; //不断 创建节点,最后总指向空 
    p->next=NULL;
    pTail=p;
   } 
  } 
 }
 return pHead;
}

定义头尾节点,头节点为空指向下一个节点,所以信息打印的时候要跳过他,不然会乱码也就是从pHead->next开始
尾节点指向p,p指向下个空结点,然后尾节点指向空,这样保证每次都指向最末尾

关键代码

   pNode pTail=pHead;//头尾节点
   pHead->next=NULL;//头节点为空
   pNode p=(pNode)malloc(sizeof(struct Node));//创建节点
   pTail->next=p; //不断 创建节点,最后总指向空 
   p->next=NULL;
   pTail=p;

数据打印

void print(pNode pHead)//数据打印
{
	pNode p=pHead->next;//跳过头节点,头节点为空 
	while(p!=NULL)
	{
		printf("学号     \t姓名\t语文\t数学\t英语\t总分\n"); 
		printf("%s     \t%s\t%g\t%g\t%g\t%g\n",p->no,p->name,p->score[0],p->score[1],p->score[2],p->total);
		p=p->next;
	}
}

pNode p=pHead->next;//跳过头节点,头节点为空 ,这句话保证数据不出错,然后循环指向下一个

数据排序(选择)

void sort(pNode pHead)//排序 从小到大 
{
	int i,j;
	pNode p,q;
	for(i=0,p=pHead->next;i<2;i++,p=p->next)
	{
		for(j=i+1,q=p->next;j<3;j++,q=q->next)
		{
			//交换数据
			if(strcmp(p->no,q->no)>0)
			{
				//交换数据 
				float temp;temp=p->total;p->total=q->total;q->total=temp;
				temp=p->score[0];p->score[0]=q->score[0];q->score[0]=temp;
				temp=p->score[1];p->score[1]=q->score[1];q->score[1]=temp;
				temp=p->score[2];p->score[2]=q->score[2];q->score[2]=temp;
				temp=p->total;p->total=q->total;q->total=temp; 
				char c[20];strcpy(c,p->no);strcpy(p->no,q->no);strcpy(q->no,c);
				strcpy(c,p->name);strcpy(p->name,q->name);strcpy(q->name,c);
			}
		}
	}
}

思路和数组交换差不多,定义两个节点p,q然后指向数据,开始进行交换,但都要跳过头节点,指向下一个,所以
p=pHead->next,q=p->next;这两句不能少,选择是这样,

交换用一个临时变量即可,c++有swap可以直接换,C语言只能自己写,字符数组交换用strcpy

查找数据

void find(pNode head,char ID[])//数据查找,根据ID查找 
{
	int flag=0;
	if(head->next==NULL)
	{
		printf("error:空链表");
	}
	pNode p=head;
	while(p!=NULL)
	{
		if(!strcmp(p->no,ID))
		{
			printf("学号     \t姓名\t语文\t数学\t英语\t总分\n"); 
            printf("%s     \t%s\t%g\t%g\t%g\t%g\n",p->no,p->name,p->score[0],p->score[1],p->score[2],p->total);
            flag=1;
		}
		p=p->next;
	}
	if(!flag)
	{
		printf("记录中未有此人\n");
	}
	
} 

这和循环创建链表差不多,加了if判断罢了

删除数据

void delete(pNode head,char ID[])//数据删除
{	
	if(head->next==NULL)
	{
		printf("error:空链表\n");
		exit(0);
	}
	pNode p=head;
	head=head->next;
	while(head!=NULL)
   {
		if(!strcmp(head->no,ID))
		{
			p->next=head->next;
			free(head);
		}
		head=head->next;
		p=p->next;
	}
}

删除数据,先根据判断找节点,不断指向下一个节点,创立两个节点,一个在前,一个在后,即p,q,然后找到后,令前节点p指向q的下一个节点,然后释放q,不然有野指针
关键代码:

    pNode p=head;
	head=head->next;
	if 找到
	    p->next=head->next;
			free(head);
	else
	head=head->next;
		p=p->next;

或者用q保存要删除节点的地址位置;也就是原来的head=head->next先不要,当找到后令q=p->next,让他指向下一个节点;
赋值:p->next=q->next
free(q)释放内存
代码

q=p->next;
p->next=q->next;
free(q);

插入数据

void insert(pNode pHead,int pos,char id[],char Name[],float chinese,float math,float english,float sum)//数据插入,前插 
{
	int i=0;
	pNode p=pHead;
	while((p!=NULL)&&(i<pos))
	{
		p=p->next;
		i++;
	}
	if(p==NULL||i>pos)//插入位置非法
	{
		printf("插入位置非法");
		exit(0);
	}
	pNode new_node=(pNode)malloc(sizeof(struct Node));
    //数据插入 
    strcpy(new_node->name,Name);
    strcpy(new_node->no,id);
    new_node->score[0]=chinese;new_node->score[1]=math;new_node->score[2]=english;
    new_node->total= sum;
    new_node->next=p->next;
	p->next=new_node; 
}

这个和删除差不多,多了一个增加节点的问题,同时根据i的赋值,它可以从0开始也可以从1开始
创立一个节点,节点存信息,然后让这个节点指向之前节点
new_node->next=p->next;
p->next=new_node;

主函数调用

int main()
{
pNode head=create(); 
return 0;
}

全部代码

#include<stdio.h>
#include<string.h>
#include<math.h> 
struct Node
{
  char name[20];     // 学生姓名
  char no[20];      // 学生学号
  float score[3];    // score数组分别存储语文、数学、英语成绩
  float total;       // 总分
  struct Node *next; // 下一个结点的地址
};
typedef struct Node *pNode; 
//实现链表的创建(根据文件scores.txt读入)、排序、输出、节点查找、插入、删除
pNode create()//信息读入和链表创建 ,假定scores.txt的文件读入姓名-学号-成绩,每个人一行 
{
 //人数就三个,所以长度为三
 pNode pHead=(pNode)malloc(sizeof(struct Node));
 if(NULL==pHead)
 {
  printf("创建失败");
  exit(-1);//检验是否成功 
 }
 else
 {
  pNode pTail=pHead;//头尾节点
  pHead->next=NULL;//头节点为空
  for(i=0;i<3;i++)//长度可以自定义,循环创建 
  {
   pNode p=(pNode)malloc(sizeof(struct Node));
   if(p==NULL)
   {
    printf("创建失败");
    exit(-1);//检验是否成功 
   }
   else
   {
    //文件读入信息
    scanf("%s",p->no);
    scanf("%s",p->name);
    scanf("%f",&(p->score[0]));
    scanf("%f",&(p->score[1]));
    scanf("%f",&(p->score[2]));
    scanf("%f",&(p->total));
    pTail->next=p; //不断 创建节点,最后总指向空 
    p->next=NULL;
    pTail=p;
   } 
  } 
 }
 return pHead;
}
void insert(pNode pHead,int pos,char id[],char Name[],float chinese,float math,float english,float sum)//数据插入,前插 
{
	int i=0;
	pNode p=pHead;
	while((p!=NULL)&&(i<pos))
	{
		p=p->next;
		i++;
	}
	if(p==NULL||i>pos)//插入位置非法
	{
		printf("插入位置非法");
		exit(0);
	}
	pNode new_node=(pNode)malloc(sizeof(struct Node));
    //数据插入 
    strcpy(new_node->name,Name);
    strcpy(new_node->no,id);
    new_node->score[0]=chinese;new_node->score[1]=math;new_node->score[2]=english;
    new_node->total= sum;
    new_node->next=p->next;
	p->next=new_node; 
}
void delete(pNode head,char ID[])//数据删除
{	
	if(head->next==NULL)
	{
		printf("error:空链表\n");
		exit(0);
	}
	pNode p=head;
	head=head->next;
	while(head!=NULL)
   {
		if(!strcmp(head->no,ID))
		{
			p->next=head->next;
			free(head);
		}
		head=head->next;
		p=p->next;
	}
}
void find(pNode head,char ID[])//数据查找,根据ID查找 
{
	int flag=0;
	if(head->next==NULL)
	{
		printf("error:空链表");
	}
	pNode p=head;
	while(p!=NULL)
	{
		if(!strcmp(p->no,ID))
		{
			printf("学号     \t姓名\t语文\t数学\t英语\t总分\n"); 
            printf("%s     \t%s\t%g\t%g\t%g\t%g\n",p->no,p->name,p->score[0],p->score[1],p->score[2],p->total);
            flag=1;
		}
		p=p->next;
	}
	if(!flag)
	{
		printf("记录中未有此人\n");
	}
	
} 
void sort(pNode pHead)//排序 从小到大 
{
	int i,j;
	pNode p,q;
	for(i=0,p=pHead->next;i<2;i++,p=p->next)
	{
		for(j=i+1,q=p->next;j<3;j++,q=q->next)
		{
			//交换数据
			if(strcmp(p->no,q->no)>0)
			{
				//交换数据 
				float temp;temp=p->total;p->total=q->total;q->total=temp;
				temp=p->score[0];p->score[0]=q->score[0];q->score[0]=temp;
				temp=p->score[1];p->score[1]=q->score[1];q->score[1]=temp;
				temp=p->score[2];p->score[2]=q->score[2];q->score[2]=temp;
				temp=p->total;p->total=q->total;q->total=temp; 
				char c[20];strcpy(c,p->no);strcpy(p->no,q->no);strcpy(q->no,c);
				strcpy(c,p->name);strcpy(p->name,q->name);strcpy(q->name,c);
			}
		}
	}
}
void print(pNode pHead)//数据打印
{
	pNode p=pHead->next;//跳过头节点,头节点为空 
	while(p!=NULL)
	{
		printf("学号     \t姓名\t语文\t数学\t英语\t总分\n"); 
		printf("%s     \t%s\t%g\t%g\t%g\t%g\n",p->no,p->name,p->score[0],p->score[1],p->score[2],p->total);
		p=p->next;
	}
}
int main()
{
	printf("==================================================\n输入数据:\n");
	pNode head=create(); 
	printf("\n");
	print(head);
	printf("===================================================\n排序后的数据:\n");
	sort(head);
	print(head);
	printf("\n");
	printf("===================================================\n查找数据(输入ID):\n");
	char ID[20];
	scanf("%s",ID);
	printf("\n");
	find(head,ID);
	printf("====================================================\n删除数据(输入ID): \n");
	scanf("%s",ID);
	printf("\n");
	delete(head,ID);
	print(head);
	printf("====================================================\n增加数据(从0开始编号,前插): \n");
	char name[20],id[20];
    float ch,ma,en,su;
    int n; 
    scanf("%d%s%s%f%f%f%f",&n,id,name,&ch,&ma,&en,&su);
    insert(head,n,id,name,ch,ma,en,su);//数据插入 
    printf("\n");
    printf("=======================================================\n");
    print(head);
    printf("=======================================================\n");
	return 0;
} 

结果
在这里插入图片描述
在这里插入图片描述

参考博客:
学习心得:链表的操作
讲真这个讲的我是最明白的

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值