初次用到链表的排序还是在C语言课程设计上,当时想着要把代码发到CSDN上,结果一拖再拖到现在。
我的课程设计项目为“学生成绩管理系统”,所用链表为双向链表链表。
涉及到成绩管理则避免不了成绩的排序。
结构体中的项目包括:
- 学生成绩;
- 学生姓名;
- 学生学号;
- 结构体的头指针与尾指针;
先创建结构体:
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
struct student
{
struct student *ahead;
float grade[10];
char name[10];
char x[10];
struct student *next;
}*head, *end, *New, *get, *stu;
设置head指针和end指针。head指向头结点,end始终指向尾节点。
输入数据:
int input(int N, char **G)//数据输入
//变量说明:“N”为考试的科目数量,此处**G为字符串指针数组,其中存储着考试科目。
{
int i, c = 1, icount = 0, s[10], j, k, d;
char r[10];
for (j = 0; j < 10; j++)
s[j] = 0;
while (c)
{
New = (struct student *)malloc(sizeof(struct student));
printf("\t\t输入该名学生姓名(结束请按‘0’):");
scanf("%s", New->name);
if (New->name[0] != 48)
{
printf("\t\t输入该名学生学号:");
scanf("%s", r);
icount++;
strcpy(New->x, r);
New->grade[N] = 0;
for (i = 0; i < N; i++)
{
printf("\t\t%s成绩:", G[i]);
scanf("%f", &New->grade[i]);
if (New->grade[i] < 60)
s[i]++;
New->grade[N] = New->grade[N] + New->grade[i];
}
strcpy(New->mima, "1234");
end->next = New;
New->ahead = end;
end = New;
end->next = NULL;
}
}
else
{
c = 0;
}
}
链表已经创建完成,现在只需要向其中添加数据,下一步祭出我屌炸天 的链表节点排序代码?
此代码运用简单选择排序的排序方法。即,先比较两个节点中数据的大小,并两个选中较大或较小的一个。并让选中的节点与下一个节点中的数据比较直到最后一个节点。比较完毕后将最小的节点接到链表的最后。
当然,开始排序之前,我创建了一个空节点让其存储成绩的数组的每一个元素都等于“-1”将其接到了链表的最后作为新的有序链表与旧的无序链表的边界。在排序完毕后程序自动将此空节点删除。得到的就是新的有序数组。
1.排序前的准备阶段(假设此处为升序排序)
主要步骤为:
- 创建三个结构体指针“ *min”、“*xunow”、“ *uend”;
- uend就是我添加的边界空指针;
int paixu(int N)//成绩排序
{
int i;//在程序的后便会让用户选择升序还是降序排序,变量i的作用是根据i的值选择排序方式。若i为1则降序排列,0则升序排列
struct student *min, *xunow, *uend;
uend = (struct student *)malloc(sizeof(struct student));
uend->grade[0] = -1;
uend->next = NULL;
uend->ahead = end;
end->next = uend;
2.排序执行阶段
上一步中创建的三个结构体指针已经用掉了一个,在这一步中“min”代表比较值最小的节点。"xunow"表示当前与min节点比较的节点。
- 通过简单选择排序找出旧链表中的最小值节点;
- 将此最小值节点接到链表的最后;
printf("\n\t\t升序排序(0) 降序排序(1)\n\t\t");
scanf("%d", &i);
for (min = head->next; min->next->grade[0] != -1; min = head->next)
{
xunow = min->next;
if (i == 0)
{
do
{
if (xunow->grade[0] < min->grade[0])
{
min = xunow;
}
xunow = xunow->next;
} while (xunow->next->grade[0] != -1 && xunow->grade[0] != -1 && min->next->grade[0] != -1);
min->ahead->next = min->next;
min->next->ahead = min->ahead;
min->ahead = uend;
uend->next = min;
uend = min;
}
else
{
do
{
if (xunow->grade[0] > min->grade[0])
{
min = xunow;
}
xunow = xunow->next;
} while ( xunow->grade[0] != -1 && min->next->grade[0] != -1);
min->ahead->next = min->next;
min->next->ahead = min->ahead;
min->ahead = uend;
uend->next = min;
uend = min;
}
}
3.排序完成收尾阶段
在执行完上步代码后,表明排序基本完成。按照步骤,此时边界空节点的旧链表一侧还有最后一个具有有效数据的节点,即存储最大数据的节点。现在只需要将此节点与边界节点一起转移到整个链表的最后再删除边界节点,就能最终完成链表的排序。
min = head->next;
xunow = min->next;
head->next = xunow->next;
xunow->next->ahead = head;
xunow->next = NULL;
min->ahead = uend;
uend->next = min;
uend = xunow;
end = uend->ahead;
uend->ahead->next = NULL;
free(uend);
return 0;
}
这就是自己在本学期的课程设计中,灵光一现敲出的链表节点排序代码。虽然不够简洁但不管怎么样这段代码还是实现了功能,即节点排序。