返回顶部

被C语言链表折磨的一天 Σ( ° △ °|||)︴

OIer竟沦落到这个地步——>C语言课要免修就要拿C语言来写一个链表,而且不能拿数组模拟 ( ̄△ ̄;),为了免修,OIer只好学习一手小小指针。

首先需要知道指针是什么:
int *a char *a[] double *a 以上三个都是指针,前面的数据类型如int只是代表这个指针所指向的数据类型,指针的定义方式可以总结为 数据类型 *指针名 ,可以把指针类型的变量单独看成一种数据类型。定义时前面写的数据类型不会影响其本身类型。也就是说在结构体里面定义一个指向下一个结构体的指针时,会在struct里面出现struct。
如果说把指针比作房卡,那么前面的数据类型就是客人的类型,客人的类型不会影响房卡本身的性质和功能,只是说对于一群客人开不同的房型,不同的房间数量时我们需要提前预留的空间不同 这也是指针和数组模拟的最大区别。指针相对来说更加难以理解但是更加方便快捷。只是需要注意NULL是空指针。用于初始化指针的值,方便后续判断结尾。同时NULL不会指向任何空间也就不会跳到什么奇奇怪怪的地方去。
但其实很多地方和c++的语言逻辑思路没什么区别的,最重要的就是如何使用这个指针变量。本次讲解主要以代码的解读为主。
板子代码里面为指针型变量的有结构体的next指针struct stud *nxt;create函数里面用于指向链表头和链表尾的指针以及指向新节点的指针struct stud *h = nul, *tl = nul, *Node;暂时先看这几个,可以发现,指针类型的变量在使用的时候就可以当成其指向的元素类型来使用,只是需要在最开始的时候定义的时候加入如一个*符号。
那么由此我们总结一下指针型变量的使用————类似于万能房卡的存在,只是每次刷新的房间之前需要将这张房卡的ID改一下,但实际上这张房卡里面并不能住人,可以通过房卡来入住或者退房但是房卡本身只是一个指向性的道具。对应到指针就是,指针在声明过后可以随意指向声明的数据类型的存储空间,也就是说int *a那么a指针就可以指向任何int类型的变量,只要保证每次指针指向的空间所存储的数据是int类型就可以。但是a不能指向其他任何类型的变量。
由此我们来开板子对于指针的使用:
先看一段代码:

struct stud *creat_list() {
	struct stud *h = nul, *tl = nul, *Node;
//h是head,tl是tail,node是用于新开一个结构体来储存信息
//这些存储的都是地址,不像c++需要下标,这个只需要指向地址
//只能说各有优劣
	int id;
	char name[20];
	double score;
	char tag;

	do {
		scanf("%d %s %lf",&id,name,&score);
		Node=(struct stud *)malloc(sizeof(struct stud));
//核心出装,给出node一定空间,之后这个节点地址就是现在的node
		Node->ID=id;
		strcpy(Node->name,name);
		Node->score=score;
		Node->nxt=nul;
		if (h==nul) {//判断开头
			h=Node;
			tl=Node;+
		} else {//接在后面
			tl->nxt=Node;
			tl=Node;
		}
		printf("y->continue|||||||||||n->stop");
		scanf(" %c",&tag);
	} while (tag=='y');
	return h;//返回一个首地址,知道这个首地址就足够了
}

我们注意到此处的指针使用了一个神奇的符号->,这个符号很神奇,是单独给指针使用的而且还是定向给结构体和类,他的作用是将指针解码并且直接调用箭头后面的元素/函数。举个栗子:
Node->score=score;这段代码其实可以写成(*Node).score=score;也就是说->*这个符号的指针解码为元素和.的调用结合在了一起。在具体书写的时候看个人书写习惯来使用。
如下:

struct stud *creat_list() {
	struct stud *h = nul, *tl = nul, *Node;
	int id;
	char name[20];
	double score;
	char tag;
	do {
		scanf("%d %s %lf",&id,name,&score);
		Node=(struct stud *)malloc(sizeof(struct stud));
		(*Node).ID=id;
		strcpy((*Node).name,name);
		(*Node).score=score;
		(*Node).nxt=nul;
		if (h==nul) {
			h=Node;
			tl=Node;
		} else {
			(*tl).nxt=Node;
			tl=Node;
		}
		printf("y->continue|||||||||||n->stop");
		scanf(" %c",&tag);
	} while (tag=='y');
	return h;
}
*/

再然后就是需要注意的一段函数Node=(struct stud *)malloc(sizeof(struct stud));逐步解析这段函数的作用malloc函数的作用就是申请动态开一个大小为一个结构体stud的空间,并且返回这一段空间的首地址。而开头的(struct stud *)则是强制数据类型的转换。将空间分配给一个结构体。
然后其他的都是一些比较细碎的东西,比如冒泡排序和归并算法的一些细节操作。
建议好好复习。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define nul NULL
struct stud {
	int ID;
	char name[20];
	double score;
	struct stud *nxt;
//此处struct stud是指针指向元素的元素类型
//其实是定义了一个指针而不是在结构体里面定义一个结构体
};
struct stud *creat_list() {
	struct stud *h = nul, *tl = nul, *Node;
//h是head,tl是tail,node是用于新开一个结构体来储存信息
//这些存储的都是地址,不像c++需要下标,这个只需要指向地址
//只能说各有优劣
	int id;
	char name[20];
	double score;
	char tag;

	do {
		scanf("%d %s %lf",&id,name,&score);
		Node=(struct stud *)malloc(sizeof(struct stud));
//核心出装,给出node一定空间,之后这个节点地址就是现在的node
		Node->ID=id;
		strcpy(Node->name,name);
		Node->score=score;
		Node->nxt=nul;
		if (h==nul) {//判断开头
			h=Node;
			tl=Node;+
		} else {//接在后面
			tl->nxt=Node;
			tl=Node;
		}
		printf("y->continue|||||||||||n->stop");
		scanf(" %c",&tag);
	} while (tag=='y');
	return h;//返回一个首地址,知道这个首地址就足够了
}
/*
struct stud *creat_list() {
	struct stud *h = nul, *tl = nul, *Node;
	int id;
	char name[20];
	double score;
	char tag;
	do {
		scanf("%d %s %lf",&id,name,&score);
		Node=(struct stud *)malloc(sizeof(struct stud));
		(*Node).ID=id;
		strcpy((*Node).name,name);
		(*Node).score=score;
		(*Node).nxt=nul;
		if (h==nul) {
			h=Node;
			tl=Node;
		} else {
			(*tl).nxt=Node;
			tl=Node;
		}
		printf("y->continue|||||||||||n->stop");
		scanf(" %c",&tag);
	} while (tag=='y');
	return h;
}
*/

void sort_list(struct stud*h) {
	if(h==nul||h->nxt==nul) {
		return ;
	}
	int tag;
	struct stud *nowp;
	struct stud *lptr=nul;
	int	ListId;
	char Listname[20];
	double Listscore;
	do {
		tag=0;
		nowp=h;
		while(nowp->nxt!=lptr) {
			if(nowp->score<nowp->nxt->score) {

				ListId=nowp->ID;
				nowp->ID=nowp->nxt->ID;
				nowp->nxt->ID=ListId;

				strcpy(Listname,nowp->name);
				strcpy(nowp->name,nowp->nxt->name);
				strcpy(nowp->nxt->name,Listname);

				Listscore=nowp->score;
				nowp->score=nowp->nxt->score;
				nowp->nxt->score=Listscore;

				tag=1;
			}
			nowp=nowp->nxt;
		}
		lptr=nowp;

	} while(tag);
}
struct stud  *Merge_list(struct stud *lsta,struct stud *lstb) {
	if(lsta==nul)return lstb;
	if(lstb==nul)return lsta;
	struct stud *h=nul, *tl=nul;
	struct stud *Lista=lsta, *Listb=lstb;
	if(Lista->score>=Listb->score) {
		h=Lista;
		Lista=Lista->nxt;
	} else {
		h=Listb;
		Listb=Listb->nxt;
	}
	tl=h;
	while(Lista!=nul&&Listb!=nul) {
		if(Lista->score>=Listb->score) {
			tl->nxt=Lista;
			Lista=Lista->nxt;
		} else {
			tl->nxt=Listb;
			Listb=Listb->nxt;
		}
		tl=tl->nxt;
	}
	if(Lista!=nul) {
		tl->nxt=Lista;
	} else {
		tl->nxt=Listb;
	}
	return h;
}

void print_list(struct stud *List) {
	struct stud *h=List;
	while(h!=nul) {
		printf("ID:%d\t Name:%s\t Score%.2lf\n",h->ID,h->name,h->score);
		h=h->nxt;
	}
	return ;
}
int main(void) {
	printf("List1 ----------->\n");
	printf("Id/name/score\n");
	struct stud *lista=creat_list();
	printf("List2 ----------->\n");
	printf("Id/name/score\n");
	struct stud *listb=creat_list();
	sort_list(lista);
	print_list(lista);
	sort_list(listb);
	print_list(listb);
	struct stud *listc=Merge_list(lista,listb);
	print_list(listc);
	return 0;
}
posted @ 2025-10-18 20:00  Noxaris  阅读(8)  评论(0)    收藏  举报
1 2 3 1
浏览器标题切换
浏览器标题切换end