您正在交换节点中的 数据,而不是链接指针。
虽然您可以这样做,但通常只有链接指针会被交换。假设你的struct 有(另外),比如:int array[1000000]; 作为一个元素。您必须交换 那个,与仅更改指针相比,这将 非常 慢。
而且,您只需 一个 传递数据。因此,您可能会在列表的前面获得最低值,但所有其他值将保持未排序。
也就是说,对于具有 N 个元素和简单排序(具有 O(N^2) 复杂度)的列表,您需要 N 次遍历。
我不得不稍微重构一下你的代码。
我想出的算法是有一个临时的“目的地”列表[最初是空的]。
对于每次遍历,都会扫描原始列表中的最小/最低元素。
该元素从源列表中删除并附加到目标列表中。
最后将临时列表的头部地址复制到原始列表的head元素中。
无论如何,这是代码。我试图尽可能多地注释它。它编译干净,我已经检查过它的正确性。但是,我没有测试它,所以它可能有一些错误。但是,它应该可以帮助您入门。
#include <stdio.h>
typedef struct Node {
void *data;
int score;
struct Node *next;
} Node;
typedef struct {
Node *head;
} Linked_List;
void
SortList(Linked_List *srclist)
{
Node *dsthead = NULL;
Node *dstprev = NULL;
// do N passes on the list
while (1) {
// get next element in source list -- stop when empty
Node *srcbest = srclist->head;
if (srcbest == NULL)
break;
// find smallest node in remaining list
Node *bestprev = NULL;
Node *curprev = NULL;
for (Node *cursrc = srcbest; cursrc != NULL; cursrc = cursrc->next) {
if (cursrc->score < srcbest->score) {
srcbest = cursrc;
bestprev = curprev;
}
curprev = cursrc;
}
// add selected node to tail of destination list
if (dsthead == NULL)
dsthead = srcbest;
else
dstprev->next = srcbest;
dstprev = srcbest;
// remove selected node from source list
if (bestprev != NULL)
bestprev->next = srcbest->next;
else
srclist->head = srcbest->next;
// fix the tail of destination list
dstprev->next = NULL;
}
// set new head of original list
srclist->head = dsthead;
}
更新:
我也试过这个,但仍然没有排序给我相同的链表。
自从我的原始帖子以来,我创建了一个测试程序。该算法有效[如发布]。所以,你的代码中一定有其他东西。
该算法类似于插入排序。我添加了冒泡排序变体。
这是完整的工作代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node {
void *data;
int score;
struct Node *next;
} Node;
typedef struct {
Node *head;
Node *tail;
int count;
} Linked_List;
#define DOTEST(_fnc,_count) \
dotest(_fnc,#_fnc,_count)
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
enum {
OPT_SWAPFLG = 1u << 0,
OPT_SHORTEN = 1u << 1,
};
double tsczero;
double
tscgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_MONOTONIC,&ts);
sec = ts.tv_nsec;
sec /= 1e9;
sec += ts.tv_sec;
sec -= tsczero;
return sec;
}
int
show(Node *cur)
{
int score;
if (cur != NULL)
score = cur->score;
else
score = -1;
return score;
}
// SortList -- insertion sort
void
SortList(Linked_List *srclist)
{
Node *dsthead = NULL;
Node *dstprev = NULL;
// do N passes on the list
while (1) {
// get next element in source list -- stop when empty
Node *srcbest = srclist->head;
if (srcbest == NULL)
break;
// find smallest node in remaining list
Node *bestprev = NULL;
Node *curprev = NULL;
for (Node *cursrc = srcbest; cursrc != NULL; cursrc = cursrc->next) {
if (cursrc->score < srcbest->score) {
srcbest = cursrc;
bestprev = curprev;
}
curprev = cursrc;
}
// add selected node to tail of destination list
if (dsthead == NULL)
dsthead = srcbest;
else
dstprev->next = srcbest;
dstprev = srcbest;
// remove selected node from source list
if (bestprev != NULL)
bestprev->next = srcbest->next;
else
srclist->head = srcbest->next;
// fix the tail of destination list
dstprev->next = NULL;
}
// set new head of original list
srclist->head = dsthead;
}
// SwapCom -- bubble sort
void
SwapCom(Linked_List *list,unsigned int opt)
{
Node *dsthead = NULL;
Node *dstprev = NULL;
Node *tail = NULL;
int swapflg = 1;
// do N passes on the list -- stop early if list becomes sorted
while (swapflg) {
if (opt & OPT_SWAPFLG)
swapflg = 0;
Node *prev = list->head;
if (prev == NULL)
break;
dbgprt("SwapList: START\n");
Node *next;
Node *pprev = NULL;
for (Node *cur = prev->next; cur != NULL; cur = next) {
next = cur->next;
dbgprt("SwapCom: CUR head=%d pprev=%d prev=%d cur=%d next=%d\n",
show(list->head),show(pprev),show(prev),show(cur),show(next));
// last element is always in sort
if (cur == tail) {
dbgprt("SwapCom: SHORT\n");
break;
}
// the two elements are already in order
if (prev->score <= cur->score) {
pprev = prev;
prev = cur;
continue;
}
// say we had to swap -- we require another pass
dbgprt("SwapCom: SWAP\n");
swapflg = 1;
// adjust the head of the list
if (prev == list->head)
list->head = cur;
// swap the link pointers
cur->next = prev;
prev->next = next;
// adjust previous
if (pprev != NULL)
pprev->next = cur;
//next = prev;
pprev = cur;
//prev = cur;
}
if (opt & OPT_SHORTEN)
tail = prev;
}
}
// SwapEarly -- bubble sort
void
SwapEarly(Linked_List *list)
{
SwapCom(list,OPT_SWAPFLG);
}
// SwapShort -- bubble sort
void
SwapShort(Linked_List *list)
{
SwapCom(list,OPT_SWAPFLG | OPT_SHORTEN);
}
void
split(Linked_List *list,Linked_List *listl,Linked_List *listr)
{
int c2 = list->count / 2;
int idx = 1;
Node *rhs;
// find the midpoint
for (rhs = list->head; rhs != NULL; rhs = rhs->next, ++idx) {
if (idx >= c2)
break;
}
listl->head = list->head;
listl->count = c2;
listr->count = list->count - c2;
listr->head = rhs->next;
rhs->next = NULL;
}
void
merge(Linked_List *list,Linked_List *listl,Linked_List *listr)
{
Node *lhs = listl->head;
Node *rhs = listr->head;
Node *prev;
Node *cur;
list->head = NULL;
list->count = 0;
prev = NULL;
while ((lhs != NULL) && (rhs != NULL)) {
if (lhs->score <= rhs->score) {
cur = lhs;
lhs = lhs->next;
listl->count -= 1;
}
else {
cur = rhs;
rhs = rhs->next;
listr->count -= 1;
}
if (prev != NULL)
prev->next = cur;
else
list->head = cur;
list->count += 1;
prev = cur;
prev->next = NULL;
}
if (lhs != NULL) {
list->count += listl->count;
prev->next = lhs;
}
if (rhs != NULL) {
list->count += listr->count;
prev->next = rhs;
}
}
void
mergesort(Linked_List *list)
{
Linked_List listl;
Linked_List listr;
if (list->count >= 2) {
split(list,&listl,&listr);
mergesort(&listl);
mergesort(&listr);
merge(list,&listl,&listr);
}
}
// MergeSort -- merge sort
void
MergeSort(Linked_List *list)
{
mergesort(list);
}
Linked_List *
newlist(int count)
{
Linked_List *list = calloc(1,sizeof(*list));
Node *prev = NULL;
for (int idx = 1; idx <= count; ++idx) {
Node *cur = calloc(1,sizeof(*cur));
cur->score = count - idx;
if (prev != NULL)
prev->next = cur;
else
list->head = cur;
list->tail = cur;
list->count += 1;
prev = cur;
}
return list;
}
void
freelist(Linked_List *list)
{
Node *next;
for (Node *cur = list->head; cur != NULL; cur = next) {
next = cur->next;
free(cur);
}
free(list);
}
int
chklist(Linked_List *list)
{
Node *prev = list->head;
Node *cur;
int idx = 0;
int err = 0;
if (prev != NULL)
cur = prev->next;
else
cur = NULL;
for (; cur != NULL; cur = cur->next, ++idx) {
if (prev->score > cur->score) {
printf("chklist: ERROR index %d -- prev=%d cur=%d\n",idx,prev,cur);
if (++err > 10)
break;
}
prev = cur;
}
if (err)
exit(1);
// get the count
idx += 1;
return idx;
}
void
prtlist(Linked_List *list,const char *reason)
{
int totlen = 0;
totlen += printf("%s:",reason);
for (Node *cur = list->head; cur != NULL; cur = cur->next) {
totlen += printf(" %d",cur->score);
if (totlen >= 70) {
printf("\n");
totlen = 0;
}
}
if (totlen > 0)
printf("\n");
}
void
dotest(void (*sort)(Linked_List *),const char *reason,int count)
{
Linked_List *list;
int prtflg = (count <= 100);
printf("\n");
printf("Testing %s for %d elements ...\n",reason,count);
list = newlist(count);
if (prtflg)
prtlist(list,"Unsorted");
double tscbeg = tscgetf();
sort(list);
double tscend = tscgetf();
tscend -= tscbeg;
if (prtflg)
prtlist(list,"Sorted");
int chk = chklist(list);
if (chk != count) {
printf("dotest: check count mismatch -- expected: %d actual: %d\n",
count,chk);
exit(1);
}
freelist(list);
double rate;
#if 0
rate = count;
rate /= tscend;
#else
rate = tscend;
rate /= count;
#endif
printf("ELAPSED: %.9f RATE: %.9f\n",tscend,rate);
fflush(stdout);
}
int
main(void)
{
int counts[] = { 10, 100, 1000, 10000, 100000, -1 };
tsczero = tscgetf();
for (int idx = 0; ; ++idx) {
int count = counts[idx];
if (count < 0)
break;
printf("\n");
for (int idx = 0; idx <= 70; ++idx)
printf("-");
printf("\n");
DOTEST(SortList,count);
DOTEST(SwapEarly,count);
DOTEST(SwapShort,count);
DOTEST(MergeSort,count);
}
return 0;
}
这是程序输出:
-----------------------------------------------------------------------
Testing SortList for 10 elements ...
Unsorted: 9 8 7 6 5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9
ELAPSED: 0.000000696 RATE: 0.000000070
Testing SwapEarly for 10 elements ...
Unsorted: 9 8 7 6 5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9
ELAPSED: 0.000001120 RATE: 0.000000112
Testing SwapShort for 10 elements ...
Unsorted: 9 8 7 6 5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9
ELAPSED: 0.000000696 RATE: 0.000000070
Testing MergeSort for 10 elements ...
Unsorted: 9 8 7 6 5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9
ELAPSED: 0.000000835 RATE: 0.000000083
-----------------------------------------------------------------------
Testing SortList for 100 elements ...
Unsorted: 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79
78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55
54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99
ELAPSED: 0.000031237 RATE: 0.000000312
Testing SwapEarly for 100 elements ...
Unsorted: 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79
78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55
54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99
ELAPSED: 0.000083257 RATE: 0.000000833
Testing SwapShort for 100 elements ...
Unsorted: 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79
78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55
54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99
ELAPSED: 0.000045619 RATE: 0.000000456
Testing MergeSort for 100 elements ...
Unsorted: 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79
78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55
54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99
ELAPSED: 0.000007023 RATE: 0.000000070
-----------------------------------------------------------------------
Testing SortList for 1000 elements ...
ELAPSED: 0.003071345 RATE: 0.000003071
Testing SwapEarly for 1000 elements ...
ELAPSED: 0.008256265 RATE: 0.000008256
Testing SwapShort for 1000 elements ...
ELAPSED: 0.004658966 RATE: 0.000004659
Testing MergeSort for 1000 elements ...
ELAPSED: 0.000110933 RATE: 0.000000111
-----------------------------------------------------------------------
Testing SortList for 10000 elements ...
ELAPSED: 0.312265008 RATE: 0.000031227
Testing SwapEarly for 10000 elements ...
ELAPSED: 0.829503246 RATE: 0.000082950
Testing SwapShort for 10000 elements ...
ELAPSED: 0.450563461 RATE: 0.000045056
Testing MergeSort for 10000 elements ...
ELAPSED: 0.001036259 RATE: 0.000000104
-----------------------------------------------------------------------
Testing SortList for 100000 elements ...
ELAPSED: 31.850022147 RATE: 0.000318500
Testing SwapEarly for 100000 elements ...
ELAPSED: 84.817288841 RATE: 0.000848173
Testing SwapShort for 100000 elements ...
ELAPSED: 46.089681707 RATE: 0.000460897
Testing MergeSort for 100000 elements ...
ELAPSED: 0.012533725 RATE: 0.000000125
更新 #2:
只是为了好玩,我编辑了第二个代码块以包含一个合并排序 [并更新了程序输出块]。
我也用你最后的排序算法进行了测试,但仍然没有排序。 – 查克
对于较小的数字,我的测试程序在排序后打印出列表。您可以目视检查之前和之后。
Chuck 显然您不知道如何测试列表是否已排序。向我们展示可让您确定列表是否已排序的代码。 ——库巴没有忘记莫妮卡
我的测试程序对列表是否排序进行了 [简单] 测试,如果列表未排序,则会中止。
您可以将您的排序检查代码与我的chklist 代码进行比较。
但是...
在您最近更新中发布的代码中,从文件中逐行读取的代码已损坏。我已经注释并修复了这段代码:
// and this one is my main for reading from txt file:
fp3 = fopen("10-million-password-list-top/aa.txt", "r");
if (fp3 == NULL) {
printf("Could not open the file\n");
}
#if 0
// NOTE/BUG: why have str be an array of pointers?
while (fgets(str[k], LSIZ, fp3)) {
str[k][strlen(str[k]) - 1] = '\0';
// NOTE/BUG: this _destroys_ the list on each iteration
Linked_List *char_list = create_empty_list();
// NOTE/BUG: insert_end _modifies_ list->head _directly_ -- no need to return
// the head value
char_list->head = insert_end(char_list, str[k]);
}
#else
char linebuf[1000];
Linked_List *char_list = create_empty_list();
while (fgets(linebuf,sizeof(linebuf),fp3)) {
linebuf[strlen(linebuf) - 1] = 0;
insert_end(char_list,linebuf);
}
#endif
insert_end 代码也被损坏了:
// NOTE/BUG: list->head is updated internally -- no need to return it
#if 0
Node *
insert_end(Linked_List *list, void *data)
#else
void
insert_end(Linked_List *list, const char *data)
#endif
{
Node *new_node;
Node *temp;
// NOTE/BUG: don't cast the return value of malloc
#if 0
new_node = (Node *) malloc(sizeof(Node));
#else
new_node = malloc(sizeof(*new_node));
#endif
// NOTE/BUG: this is _not_ the way to allocate space for the string
// NOTE/BUG: the next line blows away the value just obtained from malloc
#if 0
new_node->data = malloc(sizeof(char *));
new_node->data = (char *) data;
#else
new_node->data = strdup(data);
#endif
new_node->next = NULL;
if (list->head == NULL) {
list->head = new_node;
}
else {
temp = list->head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = new_node;
}
#if 0
return (list->head);
#endif
}