C 使用qsort算法对链表进行排序
我还在学习链表是如何工作的,我正在努力使用qsort算法和节点进行排序。 这就是我到目前为止所做的 所以我在代码中的某个地方遇到了崩溃,我不知道这个qsort算法是否以这种方式处理链表 代码更新C 使用qsort算法对链表进行排序,c,linked-list,C,Linked List,我还在学习链表是如何工作的,我正在努力使用qsort算法和节点进行排序。 这就是我到目前为止所做的 所以我在代码中的某个地方遇到了崩溃,我不知道这个qsort算法是否以这种方式处理链表 代码更新 void swapString(char **str1, char **str2) { char *temp = *str2; *str2 = *str1; *str1 = temp; } TCD *partition(TCD *Start, TCD *End, int (*
void swapString(char **str1, char **str2)
{
char *temp = *str2;
*str2 = *str1;
*str1 = temp;
}
TCD *partition(TCD *Start, TCD *End, int (*cmp)(const void *, const void*))
{
TCD *partitionIdx = Start;
TCD *i ;
for (i = Start; i != End; i=i->Next)
{
if (cmp(i->Titel, End->Titel) < 0)
{
swapString(&i->Titel, &partitionIdx->Titel);
partitionIdx->Prev = partitionIdx;
partitionIdx = partitionIdx->Next;
}
}
swapString(&partitionIdx->Titel, &End->Titel);
return partitionIdx;
}
void Quicksort(TCD *Start, TCD *End, int (*cmp)(const void *, const void *))
{
if (Start !=NULL && End != Start && End!= Start->Next)
{
TCD *partitionIdx = partition(Start, End, cmp);
Quicksort(Start, partitionIdx->Prev, cmp);
Quicksort(partitionIdx->Next, End, cmp);
}
}
您的代码有几个问题:
partitiondx->Prev=partitiondx代码>没有意义。它使节点指向自身。这不可能是正确的。链表的目的是让节点指向下一个节点和上一个节点,但决不指向自身
分区
正在崩溃,因为它的参数开始
有时会指向链接列表中结束
参数以外的位置。这是因为您调用函数Quicksort
,但没有确保其Start
参数不指向End
参数之外的位置
if
条件if(Start!=NULL&&End!=Start&&End!=Start->Next)
没有意义。子表达式End!=开始->下一步
测试分区的大小是否为2。如果是这种情况,则不处理分区。但是,必须对大小为2的分区进行排序,因此必须对其进行处理。只有当大小为1时,才不应处理它
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct F
{
char *Titel;
struct F *Next;
struct F *Prev;
} TCD;
void swapString( char **str1, char **str2 )
{
char *temp = *str2;
*str2 = *str1;
*str1 = temp;
}
TCD *partition( TCD *Start, TCD *End, int( *cmp )(const void *, const void*) )
{
TCD *partitionIdx = Start;
TCD *i;
for ( i = Start; i != End; i = i->Next )
{
if ( cmp( i->Titel, End->Titel ) < 0 )
{
swapString( &i->Titel, &partitionIdx->Titel );
//NOTE: I disabled the following line from the original code, as it was doing nonsense. It was causing a node to point to itself.
//partitionIdx->Prev = partitionIdx;
partitionIdx = partitionIdx->Next;
}
}
swapString( &partitionIdx->Titel, &End->Titel );
return partitionIdx;
}
void Quicksort( TCD *Start, TCD *End, int( *cmp )(const void *, const void *) )
{
//NOTE: In the following if condition, I disabled part of the original code, because a partition of two elements must be sorted
if ( Start != NULL && End != Start /*&& End != Start->Next*/ )
{
TCD *partitionIdx = partition( Start, End, cmp );
if ( Start != partitionIdx )
Quicksort( Start, partitionIdx->Prev, cmp );
if ( partitionIdx != End )
Quicksort( partitionIdx->Next, End, cmp );
}
}
// NOTE:
// The following functions are not part of the algorithm, but are only
// used to test the algorithm.
void AddToList( TCD **head, TCD **tail, char *str )
{
TCD *p;
//allocate new node and fill it with the data
p = malloc( sizeof(*p) );
assert( p != NULL );
p->Titel = str;
p->Next = NULL;
p->Prev = *tail;
//attach new node to list by updating head or next pointer
if ( *head == NULL )
*head = p;
else
(*tail)->Next = p;
//update tail pointer too
*tail = p;
}
void PrintList( FILE *stream, TCD *head )
{
TCD *p;
for ( p = head; p != NULL; p = p->Next )
{
fprintf( stream, "%s\n", p->Titel );
}
fprintf( stream, "\n" );
}
void FreeList( TCD *head )
{
TCD *p = head;
while ( p != NULL )
{
TCD *tmp = p;
p = p->Next;
free( tmp );
}
}
int main( void )
{
TCD *head = NULL, *tail = NULL;
//create linked list with a bit of unsorted test data
AddToList( &head, &tail, "string8" );
AddToList( &head, &tail, "string4" );
AddToList( &head, &tail, "string2" );
AddToList( &head, &tail, "string7" );
AddToList( &head, &tail, "string3" );
AddToList( &head, &tail, "string5" );
AddToList( &head, &tail, "string1" );
AddToList( &head, &tail, "string6" );
//print list before sorting
fprintf( stderr, "List before sort:\n" );
PrintList( stderr, head );
//do the actual sorting
Quicksort( head, tail, strcmp );
//print list after sorting
fprintf( stderr, "List after sort:\n" );
PrintList( stderr, head );
//free the linked list
FreeList( head );
return 0;
}
#包括
#包括
#包括
#包括
类型定义结构F
{
煤焦效价;
结构F*Next;
结构F*Prev;
}经颅多普勒;
无效交换(字符**str1,字符**str2)
{
char*temp=*str2;
*str2=*str1;
*str1=温度;
}
TCD*分区(TCD*开始,TCD*结束,整数(*cmp)(常量无效*,常量无效*)
{
TCD*partitionIdx=开始;
TCD*i;
for(i=Start;i!=End;i=i->Next)
{
如果(cmp(i->滴度,结束->滴度)<0)
{
交换交换(&i->Titel,&partitionDX->Titel);
//注意:我从原始代码中禁用了以下行,因为它没有意义。它导致一个节点指向自身。
//partitionIdx->Prev=partitionIdx;
partitionIdx=partitionIdx->Next;
}
}
交换交换(&partitiondx->Titel,&End->Titel);
返回分区dx;
}
无效快速排序(TCD*开始,TCD*结束,整数(*cmp)(常量无效*,常量无效*)
{
//注意:在下面的if条件中,我禁用了部分原始代码,因为必须对两个元素的分区进行排序
如果(开始!=NULL&&End!=Start/*&&End!=Start->Next*/)
{
TCD*partitionDX=分区(开始、结束、cmp);
如果(开始!=分区dx)
快速排序(开始,分区dx->Prev,cmp);
如果(分区dx!=结束)
快速排序(partitionIdx->Next,End,cmp);
}
}
//注:
//以下函数不是算法的一部分,只是
//用于测试算法。
无效添加列表(TCD**head,TCD**tail,char*str)
{
经颅多普勒;
//分配新节点并用数据填充它
p=malloc(sizeof(*p));
断言(p!=NULL);
p->Titel=str;
p->Next=NULL;
p->Prev=*尾部;
//通过更新头或下一个指针将新节点附加到列表
如果(*head==NULL)
*水头=p;
其他的
(*tail)->Next=p;
//也更新尾部指针
*尾=p;
}
无效打印列表(文件*流,TCD*头)
{
经颅多普勒;
for(p=head;p!=NULL;p=p->Next)
{
fprintf(流,“%s\n”,p->Titel);
}
fprintf(流“\n”);
}
无效自由列表(TCD*头)
{
TCD*p=头;
while(p!=NULL)
{
TCD*tmp=p;
p=p->Next;
免费(tmp);
}
}
内部主(空)
{
TCD*head=NULL,*tail=NULL;
//创建带有少量未排序测试数据的链表
AddToList(&head,&tail,“string8”);
附加列表(头、尾、弦4);
AddToList(头、尾和“string2”);
附加列表(头、尾、弦7);
AddToList(头、尾和“string3”);
AddToList(头、尾和“string5”);
AddToList(头、尾和string1);
AddToList(头、尾和“string6”);
//排序前打印列表
fprintf(stderr,“排序前的列表:\n”);
打印列表(标准,标题);
//进行实际排序
快速排序(头、尾、strcmp);
//排序后打印列表
fprintf(stderr,“排序后的列表:\n”);
打印列表(标准,标题);
//释放链接列表
自由名单(标题);
返回0;
}
非常感谢@Andreas。我写的一些无意义代码的原因是,我想用qsort算法和普通数组将代码翻译成带有链表的qsort,而不用花很多心思。@Gaston:如果你想用链表进行排序,你可以尝试一下,因为该算法对于链表更有效。注释不用于扩展讨论;这段对话已经结束。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct F
{
char *Titel;
struct F *Next;
struct F *Prev;
} TCD;
void swapString( char **str1, char **str2 )
{
char *temp = *str2;
*str2 = *str1;
*str1 = temp;
}
TCD *partition( TCD *Start, TCD *End, int( *cmp )(const void *, const void*) )
{
TCD *partitionIdx = Start;
TCD *i;
for ( i = Start; i != End; i = i->Next )
{
if ( cmp( i->Titel, End->Titel ) < 0 )
{
swapString( &i->Titel, &partitionIdx->Titel );
//NOTE: I disabled the following line from the original code, as it was doing nonsense. It was causing a node to point to itself.
//partitionIdx->Prev = partitionIdx;
partitionIdx = partitionIdx->Next;
}
}
swapString( &partitionIdx->Titel, &End->Titel );
return partitionIdx;
}
void Quicksort( TCD *Start, TCD *End, int( *cmp )(const void *, const void *) )
{
//NOTE: In the following if condition, I disabled part of the original code, because a partition of two elements must be sorted
if ( Start != NULL && End != Start /*&& End != Start->Next*/ )
{
TCD *partitionIdx = partition( Start, End, cmp );
if ( Start != partitionIdx )
Quicksort( Start, partitionIdx->Prev, cmp );
if ( partitionIdx != End )
Quicksort( partitionIdx->Next, End, cmp );
}
}
// NOTE:
// The following functions are not part of the algorithm, but are only
// used to test the algorithm.
void AddToList( TCD **head, TCD **tail, char *str )
{
TCD *p;
//allocate new node and fill it with the data
p = malloc( sizeof(*p) );
assert( p != NULL );
p->Titel = str;
p->Next = NULL;
p->Prev = *tail;
//attach new node to list by updating head or next pointer
if ( *head == NULL )
*head = p;
else
(*tail)->Next = p;
//update tail pointer too
*tail = p;
}
void PrintList( FILE *stream, TCD *head )
{
TCD *p;
for ( p = head; p != NULL; p = p->Next )
{
fprintf( stream, "%s\n", p->Titel );
}
fprintf( stream, "\n" );
}
void FreeList( TCD *head )
{
TCD *p = head;
while ( p != NULL )
{
TCD *tmp = p;
p = p->Next;
free( tmp );
}
}
int main( void )
{
TCD *head = NULL, *tail = NULL;
//create linked list with a bit of unsorted test data
AddToList( &head, &tail, "string8" );
AddToList( &head, &tail, "string4" );
AddToList( &head, &tail, "string2" );
AddToList( &head, &tail, "string7" );
AddToList( &head, &tail, "string3" );
AddToList( &head, &tail, "string5" );
AddToList( &head, &tail, "string1" );
AddToList( &head, &tail, "string6" );
//print list before sorting
fprintf( stderr, "List before sort:\n" );
PrintList( stderr, head );
//do the actual sorting
Quicksort( head, tail, strcmp );
//print list after sorting
fprintf( stderr, "List after sort:\n" );
PrintList( stderr, head );
//free the linked list
FreeList( head );
return 0;
}