被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;
}

浙公网安备 33010602011771号