C 对包含字符串的链接列表进行排序

C 对包含字符串的链接列表进行排序,c,arrays,linked-list,mergesort,qsort,C,Arrays,Linked List,Mergesort,Qsort,所以我要做的是对只包含字符串的链表进行排序。为此,我有两个选择 选项1-动态分配一个与链表大小相同的数组以及包含该数组的字符串,将链表的内容复制到数组中,并使用qsort对其排序 选项2-实现合并排序算法以对其进行排序 其中一个问题是,如果我选择选项2而不是选项1,会花费更多的内存和时间吗?还是选项更好 我的第二个问题是,我正在尝试执行选项1,为此我有一个包含链接列表代码的头文件。 问题是在为字符串数组分配内存后,当我尝试复制内容时,我发现分割错误 节目: #include <stdlib

所以我要做的是对只包含字符串的链表进行排序。为此,我有两个选择

选项1-动态分配一个与链表大小相同的数组以及包含该数组的字符串,将链表的内容复制到数组中,并使用
qsort
对其排序

选项2-实现合并排序算法以对其进行排序

其中一个问题是,如果我选择选项2而不是选项1,会花费更多的内存和时间吗?还是选项更好

我的第二个问题是,我正在尝试执行选项1,为此我有一个包含链接列表代码的头文件。 问题是在为字符串数组分配内存后,当我尝试复制内容时,我发现分割错误

节目:

#include <stdlib.h> 
#include <stdio.h>
#include <string.h>
#include "Listas_ligadas_char.h"

int main() {
    link_char head = NULL;
    char **strings;
    head = insertEnd_char(head, "fcb");
    head = insertEnd_char(head, "bvb");
    head = insertEnd_char(head, "slb");
    head = insertEnd_char(head, "fcp");
    int len = length_char(head);
    int i = 0, j;
    strings = (char **)malloc(sizeof(char *) * len);
    link_char t;
    t = head;
    while (t != NULL && i <= len) {
        strings[i] = (char *)malloc(sizeof(char) * (strlen(t->str) + 1));
        strcpy(strings[i++], t->v.str)
        t = t->next;
    }
    for (t = head; t != NULL; t = t->next) {
        printf("* %s\n", strings[i]);
    }
}
#包括
#包括
#包括
#包括“Listas_ligadas_char.h”
int main(){
link_char head=NULL;
字符**字符串;
head=插入字符(head,“fcb”);
head=插入字符(head,“bvb”);
头部=插入字符(头部,“slb”);
head=插入字符(head,“fcp”);
int len=长度字符(头部);
int i=0,j;
字符串=(char**)malloc(sizeof(char*)*len);
链接字符;
t=头部;
而(t!=NULL&&i str)+1);
strcpy(字符串[i++],t->v.str)
t=t->next;
}
for(t=head;t!=NULL;t=t->next){
printf(“*%s\n”,字符串[i]);
}
}
头文件:

#ifndef _Listas_ligadas_char_
#define _Listas_ligadas_char_

#include <stdlib.h> 
#include <stdio.h>
#include <string.h>

typedef struct node_char {
    char *str;
    struct node_char *next;
} *link_char;

link_char lookup_str(link_char head, char *str) {
    link_char t;
    for (t = head; t != NULL; t = t->next)
        if (strcmp(t->str, str) == 0)
            return t;
    return NULL;
}

link_char NEW_str(char *str) {
    int i;
    link_char x = (link_char)malloc(sizeof(struct node_char));
    x->str = (char *)malloc(sizeof(char) * (strlen(str) + 1));
    strcpy(x->str, str);
    x->next = NULL;
    return x;
}

link_char insertEnd_char(link_char head, char *str) {
    link_char x;
    if (head == NULL)
        return NEW_str(str);
    for (x = head; x->next != NULL; x = x->next)
        ;
    x->next = NEW_str(str);
    return head;
}

int length_char(link_char head) {
    int count = 0;
    link_char x;
    for (x = head; x != NULL; x = x->next)
        count++;
    return count;
}

void print_lista_char(link_char head, int NL) {
    link_char t;
    for (t = head; t != NULL; t = t->next) {
        printf("%d * %s\n", NL, t->str);
    }
}

void FREEnode_str(link_char t) {
    free(t->str);
    free(t);
}

link_char delete_el_char(link_char head, char *str) {
    link_char t, prev;
    for (t = head, prev = NULL; t != NULL;
        prev = t, t = t->next) {
        if (strcmp(t->str, str) == 0) {
            if (t == head)
                head = t->next;
            else
                prev->next = t->next;
            FREEnode_str(t);
            break;
        }
    }
    return head;
}
#endif
\ifndef\u Listas\u ligadas\u char_
#将列表定义为连字字符_
#包括
#包括
#包括
类型定义结构节点\u字符{
char*str;
结构节点_char*next;
}*link_char;
link_char lookup_str(link_char head,char*str){
链接字符;
for(t=head;t!=NULL;t=t->next)
如果(strcmp(t->str,str)==0)
返回t;
返回NULL;
}
链接字符新字符(字符*字符){
int i;
link_char x=(link_char)malloc(sizeof(struct node_char));
x->str=(char*)malloc(sizeof(char)*(strlen(str)+1));
strcpy(x->str,str);
x->next=NULL;
返回x;
}
链接字符插入字符(链接字符头,字符*str){
链接字符x;
if(head==NULL)
返回新的_str(str);
对于(x=head;x->next!=NULL;x=x->next)
;
x->next=新的_str(str);
回流头;
}
整数长度字符(链接字符头){
整数计数=0;
链接字符x;
对于(x=head;x!=NULL;x=x->next)
计数++;
返回计数;
}
无效打印列表字符(链接字符头,int NL){
链接字符;
for(t=head;t!=NULL;t=t->next){
printf(“%d*%s\n”,NL,t->str);
}
}
无效自由节点(链接字符){
自由(t->str);
自由(t);
}
link_char delete_el_char(link_char head,char*str){
链接字符t,上一个;
对于(t=头部,prev=NULL;t!=NULL;
上一个=t,t=t->下一个){
如果(strcmp(t->str,str)==0){
如果(t==水头)
head=t->next;
其他的
上一个->下一个=t->下一个;
FREEnode_str(t);
打破
}
}
回流头;
}
#恩迪夫
顺便说一句,如果您想知道
NL
是什么,
NL
是一个变量,用于计算
stdin
的相应行,我只想打印数组,不想保留其元素

因此,如果你能说出你认为最好的选择,我将非常感激

选项1-动态分配一个与链表大小相同的数组以及包含该数组的字符串,将链表的内容复制到数组中,并使用qsort对其排序

无需将链表转换为数组。该算法也适用于链表

但是,由于您的链接列表仅为,因此不能使用(通常效率更高),而必须使用。这是因为霍尔分区方案要求能够向后遍历链表(这需要一个列表)

即使在快速排序算法中不需要将链表转换为数组,这可能仍然有意义,因为链表的性能比数组差。无论哪种方式,算法的平均值都将是O(n*logn),最坏情况下的时间复杂度将是O(n^2)

但是,由于节点只包含指向字符串的指针,所以在取消引用这些指针时,您的空间位置将不好。因此,在这种情况下,将链表转换为数组可能没有多大帮助,因为这只会改善指向字符串的指针的空间位置,而不会改善字符串本身的位置


其中一个问题是,如果我选择选项2而不是选项1,会花费更多的内存和时间吗?还是该选项更好

是链接列表的理想选择

合并排序的另一个优点是其最坏情况下的时间复杂度,即O(n*logn),而使用快速排序则是O(n^2)

对于链表,合并排序的空间复杂度为O(1),而快速排序的空间复杂度为O(logn)。但是,如果决定将列表转换为数组进行快速排序,则算法的空间复杂度将增加到O(n))


我的第二个问题是,我试图做选项1,这样做,我有一个头文件,其中包含链接列表的代码。问题是在为字符串数组分配内存后,当我尝试复制内容时,我发现分割错误

我只能帮助你,如果你提供你的问题的答案。您发布的代码不会重现该问题。它甚至不编译。以下行包含多个错误:


strcpy(strings[i++],t->v.str)
您确实有两个合理的选择:

  • 选项1通常提供最佳性能,但需要
    sizeof(link_char)*N的额外空间

  • 选项2只需要O(log(N))堆栈空间,用于使用自底向上的mergesort或类似的空间comp的挂起子列表
    for (i = 0; i < len; i++) {
        printf("* %s\n", strings[i]);
    }