c动态链表 学生管理表 简单项目练习

c动态链表 学生管理表 简单项目练习,第1张

在学习链表后发现链表的连续性,节省空间之后写了一个学生管理表的小项目 独立思考了如何删除结点(代码中是将结点跳过却没有释放结点的空间),如何增加结点与修改选中结点。


代码作为练习代码。


没有更加的精简 可能会给你在链表学习上 提供一些一些参考思路。


main()起点与menu目录
int main()
{
	Node* hand;
	init();
	return 0;
}
void menu()
{
	printf("*****************************************\n");
	printf("**************1增加学生档案**************\n");
	printf("**************2删除对应档案**************\n");
	printf("**************3查看**********************\n");
	printf("**************4更改代码******************\n");
	printf("*****************************************\n");
}

 

建立动态链表与增加结点 *** 作

在代码的主题上运用里分支语句switch语句和循环语句do while语句来进行

单链表的建立运用一个新结点和一个对为节点来配合建立。


每次选择增加档案后会再次给 pnew新结点分配空间  然后直接 在尾节点pend原有基础上连接

(在这里将建立链表的内容自己建立一个函数来进行 代码结构会简洁不少)

最后将不需要的penw结点释放

int c;   //选择 存储
	int j;   //后续 判断是否再次进行更改 *** 作的 变量
	Node* hand;
	Node* pnew, * pend;
	hand = NULL;
	pend = (Node*)malloc(sizeof(Node));//先分配队尾结点  队尾结点只要初始化一次就可以  后续新结点不断地将地址赋给队尾结点
	do {

		menu();
		printf("请选择要进行的 *** 作\n");
		scanf("%d", &c);// *** 作选择
		switch (c)
		{
		case 1:

			while (1)
			{
				pnew = (Node*)malloc(sizeof(Node));     //分配新结点的地址
				printf("请输入第%d个学生的信息:  学号:", icount + 1);
				scanf("%d", &pnew->Nu);
				if (pnew->Nu == 0)
					break;
				printf("                         姓名:", icount + 1);
				scanf("%s", &pnew->student);
				icount++;
				pnew->nu = icount;//初始化序号
				if (icount == 1)
				{
					pnew->next = NULL;
					hand = pnew;
					pend = pnew;
				}
				else
				{

					pnew->next = NULL;
					pend->next = pnew;
					pend = pnew;

				}
				pnew = (Node*)malloc(sizeof(Node));   //再次分配新结点地址
			}
			free(pnew);//释放不需要的结点;
			print(hand);
			break;
 删除数据 *** 作

这里的代码是跳过 *** 作并不是真正意义上的删除 *** 作

这里的 *** 作分为三种 删除第一个数据、中间的数据和最后的数据

三种结点的情况不一样

头节点的话直接将第二个结点的地址付给第一个之后 返回 即可

中间   遍历链表找到要删除数据的前一个和后一个 进行连接

队尾  找到前一个结点将 p->next变为NULL; 

case 2:
			hand=Delete(hand);//删除结点
			icount=resort(hand);//排序之后返回结点长度 为了后续再增加 结点时的 *** 作
			print(hand);

			break;
Node* Delete(Node* p)    //删除
{
	print(p);
	int n = 0;
	Node* pc;
	pc = p;
	printf("请选择要删除信息的序号\n");
	scanf("%d", &n);
	if (n == 1)//若删除第一个结点的判断   
	{
		pc = p->next;
		return pc;
	}
	else {


		while (p->nu != n - 1)//找到要删除结点的上一结点
		{
			p = p->next;
		}
		Node* pa, * pb;//建立中间变量 接受前结点和后结点
		pa = p;
		p = p->next;//p此时为被删除的结点
		if (p->next == NULL)//  若删除最后一个结点的判断
		{
			pa->next = NULL;
			return pc;
		}
		else
		{
			pb = p->next;//pb为被删除结点的下一结点
			pa->next = pb;
			return pc;
		}
	}
}

这里遍历链表的和寻找前后结点的 *** 作是在定义结构体时  在内放置了一个序号变量

但是删除 *** 作进行之后 序号会缺失  这就要再次给序号赋值  而且链表的长度也会有变化   所以也需要一个变量来保存长度  这一步直接在赋值序号时一并进行

int resort(Node* p)//给删减后的结点重新标序号
{
	int n = 1;
	while (p != NULL)
	{
		p->nu = n;
		n++;
		p = p->next;
	}
	return n - 1;
}
更改结点内容

这一步是最简单的一部 只需要找到结点位置   之后更改就可以了

void Change(Node* p)
{
	int n;
		printf("请输入想更改档案的序号\n");
		scanf("%d", &n);//
		while (p->nu != n)//遍历链表寻找结点
		{
			p = p->next;
		}
		printf("请输入更改后的信息\n");
		printf("学号:");
		scanf("%d", &p->Nu);
		printf("姓名:");
		scanf("%s", &p->student);
		printf("修改完成!");
}
结尾:
#include
#include
int icount = 0;

typedef struct Node
{
	int nu;
	char student[20];
	int Nu;
	struct Node* next;
}Node;

void menu()
{
	printf("*****************************************\n");
	printf("**************1增加学生档案**************\n");
	printf("**************2删除对应档案**************\n");
	printf("**************3查看**********************\n");
	printf("**************4更改代码******************\n");
	printf("*****************************************\n");
}

void print(Node* hand)
{
	printf(" 学生档案表\n");
	printf("序号     学号  姓名\n");
	while (hand != NULL)//再循环输出的时候 要注意hand的已经是下一个结点了
	{
		
		printf(" %d      %d    %s\n",hand->nu, hand->Nu, hand->student);
		printf("\n");
		hand = hand->next;
	}
}
Node* Delete(Node* p)    //删除
{
	print(p);
	int n = 0;
	Node* pc;
	pc = p;
	printf("请选择要删除信息的序号\n");
	scanf("%d", &n);
	if (n == 1)//若删除第一个结点的判断   
	{
		pc = p->next;
		return pc;
	}
	else {


		while (p->nu != n - 1)//找到要删除结点的上一结点
		{
			p = p->next;
		}
		Node* pa, * pb;//建立中间变量 接受前结点和后结点
		pa = p;
		p = p->next;//p此时为被删除的结点
		if (p->next == NULL)//  若删除最后一个结点的判断
		{
			pa->next = NULL;
			return pc;
		}
		else
		{
			pb = p->next;//pb为被删除结点的下一结点
			pa->next = pb;
			return pc;
		}
	}
}
void Change(Node* p)
{
	int n;
		printf("请输入想更改档案的序号\n");
		scanf("%d", &n);//
		while (p->nu != n)//遍历链表寻找结点
		{
			p = p->next;
		}
		printf("请输入更改后的信息\n");
		printf("学号:");
		scanf("%d", &p->Nu);
		printf("姓名:");
		scanf("%s", &p->student);
		printf("修改完成!");
}
int resort(Node* p)//给删减后的结点重新标序号
{
	int n = 1;
	while (p != NULL)
	{
		p->nu = n;
		n++;
		p = p->next;
	}
	return n - 1;
}
void init()
{
	int c;   //选择 存储
	int j;   //后续 判断是否再次进行更改 *** 作的 变量
	Node* hand;
	Node* pnew, * pend;
	hand = NULL;
	pend = (Node*)malloc(sizeof(Node));//先分配队尾结点  队尾结点只要初始化一次就可以  后续新结点不断地将地址赋给队尾结点
	do {

		menu();
		printf("请选择要进行的 *** 作\n");
		scanf("%d", &c);// *** 作选择
		switch (c)
		{
		case 1:

			while (1)
			{
				pnew = (Node*)malloc(sizeof(Node));     //分配新结点的地址
				printf("请输入第%d个学生的信息:  学号:", icount + 1);
				scanf("%d", &pnew->Nu);
				if (pnew->Nu == 0)
					break;
				printf("                         姓名:", icount + 1);
				scanf("%s", &pnew->student);
				icount++;
				pnew->nu = icount;//初始化序号
				if (icount == 1)
				{
					pnew->next = NULL;
					hand = pnew;
					pend = pnew;
				}
				else
				{

					pnew->next = NULL;
					pend->next = pnew;
					pend = pnew;

				}
				pnew = (Node*)malloc(sizeof(Node));   //再次分配新结点地址
			}
			free(pnew);//释放不需要的结点;
			print(hand);
			break;
		case 2:
			hand=Delete(hand);//删除结点
			icount=resort(hand);//排序之后返回结点长度 为了后续再增加 结点时的 *** 作
			print(hand);

			break;
		case 3:
			print(hand);
			break;
		case 4:
			do {
				Change(hand);
				
				printf("修改后的表为\n");
				print(hand);
				printf("是否继续修改?(1/0)\n");
				scanf("%d",&j);
			} while (j);
				break;
		default:
			printf("!!!未知 *** 作数!!!请重新输入\n");
			break;
		}

	} while (c);
}
int main()
{
	Node* hand;
	init();
	return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/568341.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存