【发布时间】:2017-03-25 12:09:47
【问题描述】:
我正在尝试通过更改节点的引用来使用冒泡排序算法对链表进行排序。我在很多书籍和互联网上进行了搜索,但我只找到了改变节点之间信息部分值的排序方法。 我想要做的是通过更改列表的顺序进行排序,而不是它们之间的值。 这是我的代码。 PS:排序算法不起作用。 它不是合并排序列表的重复,因为它完全是另一种算法。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define LINESIZE 128
struct Student {
float medie;
char nrMatricol[10];
char *nume;
char facltate[6];
};
struct Nod{
Student stud;
Nod* next;
};
Nod* inserareNodEnd(Nod *l,Student st)
{
Nod *nou = (Nod*)malloc(sizeof(Nod));
nou->next = NULL;//NOU->NEXT=0
nou->stud = st;
if (!l) {
//lista este goala
return nou;
}
else
{
//lista contine un nod
Nod *t = l;
while (t->next) {
t = t->next;
}
t->next = nou;
return l;
}
}
float medieStudenti(Nod *lista) {
float suma=0;
int i=0;
Nod *aux=lista;
while (aux->next) {
aux = aux->next;
suma += aux->stud.medie;
i++;
}
return suma/i;
}
Nod *stergerePrimulNodLista(Nod *l,Student *st) {
if (l) {
Nod *aux = l;
l = l->next;
aux->next = NULL;
*st = aux->stud;
//aux->next = NULL;
free(aux);
}
return l;
}
Nod* sortareLista(Nod *l) {
Nod *i=l;
Nod *j=l;
Nod *aux=l;
Nod *min=l;
min = i;
while (i->next) {
if (i->stud.medie < min->stud.medie) {
min = i;
}
i = i->next;
}
i = l;
int n = 0;
while (i->next) {
j = i->next;
while (j->next) {
if (i->stud.medie > j->stud.medie) {
aux = i->next;
i->next = j->next;
j->next = aux;
}
j = j->next;
}
i = i->next;
}
return min;
//return l;
}
void dezalocare(Nod *lista) {
Nod *aux;
aux = lista;
while (aux->next) {
lista = aux->next;
free(aux->stud.nume);
free(aux);
aux = lista;
}
}
void main()
{
FILE *f;
Student s;
Nod *list=NULL;
f = fopen("fisier.txt", "r");
char fileBuff[LINESIZE], SEPARATORI[] = { "," };
char *token;
while (fgets(fileBuff, LINESIZE, f)) {
token = strtok(fileBuff, SEPARATORI);
strcpy(s.nrMatricol, token);
//extragere token nume student din aceeasi linie
//salvata in file Buff
token = strtok(NULL, SEPARATORI);
s.nume = (char*)malloc(sizeof(char)*strlen(token) + 1);
strcpy(s.nume, token);
token = strtok(NULL, SEPARATORI);
strcpy(s.facltate, token);
//extragere tokeni medie si conversia tokenului la float
token = strtok(NULL, SEPARATORI);
s.medie = atof(token);
list = inserareNodEnd(list, s);
printf("%s %s \n", s.nrMatricol, s.nume);
}
Nod *tmp = list;
while (tmp) {
printf("\nSe afiseaza din lista");
printf("%s %s \n", tmp->stud.nrMatricol, tmp->stud.nume);
tmp = tmp->next;
}
fclose(f);
//determinarea mediei pentru studentii din lista
float media = medieStudenti(list);
printf("\nMedia este %.2f", media);
//sortare lista dupa medie(cu modificarea adreselor de legatura)
//tema dezalocare lista
//tema dezalocari la nivel de aplicatie
printf("\nAcesta este Ionel %s %s \n", s.nrMatricol, s.nume);
// list = stergerePrimulNodLista(list, &s);
tmp = list;
while (tmp) {
printf("\nSe afiseaza din lista");
printf("%s %s \n", tmp->stud.nrMatricol, tmp->stud.nume);
tmp = tmp->next;
}
tmp = list;
while (tmp) {
printf("\nSe afiseaza lista sortata");
printf("%s %s \n", tmp->stud.nrMatricol, tmp->stud.nume);
tmp = tmp->next;
}
dezalocare(list);
}
【问题讨论】:
-
我将其作为有关合并排序的问题的副本关闭,因为共识似乎是它是通过重新排列链接来对链表进行排序的最佳算法。
-
它不是重复的。这个问题问如何合并2个列表。请再读一遍 //Merge subroutine to merge两个排序的列表。你现在明白了吗?
-
注意:
struct Nod{ Student stud; Nod* next; };是 C 中的语法错误。您使用的是 C++ 编译器吗? -
Visual Studio。它工作正常
-
@Barmar - OP 似乎特别想实现冒泡排序。至于对链表进行排序的“最佳”算法,虽然我在“重复”线程中的答案中显示自下而上的合并排序对于链表排序来说是最快的,但将列表移动到数组中更快,排序数组,并从排序后的数组创建一个新列表。如果节点足够大,最快的方法是创建一个指向节点的指针数组并对指针数组进行排序,然后创建一个新列表。
标签: c sorting linked-list bubble-sort