C语言中的Quicksort字符串数组

bfagundes

我正在编写一种快速排序算法来对字符串数组进行排序。

问题是我分配左右的quicksort数组后,带有数据的数组似乎被某些东西覆盖,因为我在此打印了数组及其所有内容,但是在我使用malloc分配了其他数组之后,我将其打印了再次,我缺少一些元素。

这是输出:

Pivot: 2
Emma, Olivia, Victoria, Gwyneth, Chloe, Hayley, Scarlett,
Emma, Olivia, Victoria, Gwyneth, , , ,

有人知道发生了什么吗?缺少什么?

char **concatenate(char **array1, int n1, char *pivot, char **array2, int n2, int len){
int i=0, j=0;
int elements = n1 + n2 + 1;

// alocating array
char **concat = (char**) malloc(sizeof(*concat) * elements);
concat[0] = (char*) malloc(sizeof(*concat) * elements * len);
for(i=1; i<elements; i++)
    concat[i] = &(concat[0][i*len]);

// concatenating 
for(i=0; i<n1; i++)
    concat[i] = array1[i];
concat[i++] = pivot;
for(j=0; j<n2; j++)
    concat[i++] = array2[j];

// returning
return concat;
}

char **quicksort(char **array, int elements, int len){
// array is already sorted
if(elements < 2)
    return array;

int pivot;
int i=0, l=0, r=0;

// selecting the pivot (median)
if(elements % 2 == 0)
    pivot = ((elements + 1) / 2) -1;
else
    pivot = (elements / 2) -1;

//REMOVE
printf("Pivot: %d\n", pivot);
for(i=0; i<elements; i++)
    printf("%s, ", array[i]);
printf("\n");

// alocating arrays
char **left = (char**) malloc(sizeof(*left) * pivot);
left[0] = (char*) malloc(sizeof(*left) * pivot * len);
for(i=1; i<pivot; i++)
    left[i] = &(left[0][i*len]);

char **rigth = (char**) malloc(sizeof(*rigth) * pivot);
rigth[0] = (char*) malloc(sizeof(*rigth) * pivot * len);
for(i=1; i<pivot; i++)
    rigth[i] = &(rigth[0][i*len]);

//REMOVE
for(i=0; i<elements; i++)
    printf("%s, ", array[i]);
printf("\n");

//quicksorting
for(i=0; i<elements; i++){
    if(array[i] == array[pivot])
        continue;

    int comp = strcmp(array[i], array[pivot]);

    //REMOVE
    printf("%d: strcmp %s, %s is %d\n", i, array[i], array[pivot], comp);

    if(comp < pivot)
        left[l++] = array[i];
    else
        rigth[r++] = array[i];
}

//REMOVE
printf("concatenate(");
for(i=0; i<l; i++)
    printf("%s ", left[i]);
printf("|%s| ", array[pivot]);
for(i=0; i<r; i++)
    printf("%s ", rigth[i]);
printf(")\n");

// recursion and return
return concatenate(quicksort(left, l, len), l, array[pivot], quicksort(rigth, r, len), r, len);
}

int main(int argc, char *argv[]){
int i, j, aux;                  

char **teste = (char**) malloc(sizeof(*teste) * 7);
teste[0] = (char*) malloc(sizeof(*teste) * 7 * 128);
for(i=1; i<7; i++)
    teste[i] = &(teste[0][i*128]);
teste[0] = "Emma";
teste[1] = "Olivia";
teste[2] = "Victoria";
teste[3] = "Gwyneth";
teste[4] = "Chloe";
teste[5] = "Hayley";
teste[6] = "Scarlett";

quicksort(teste, 7, 128);

printf("AFTER\n");
for(i=0; i<7; i++)
    printf("%s, ", teste[i]);
printf("\n");

return 0;
}
WhozCraig

分配quicksort的理由为零,实际上,对于您的情况,该函数可以通过使用quick-math(char * arr [],unsigned int len)的简单接口(对于子序列调用使用pointer-math)就足够了。

提供用于交换指针的交换算法:

void swap_str_ptrs(char const **arg1, char const **arg2)
{
    const char *tmp = *arg1;
    *arg1 = *arg2;
    *arg2 = tmp;
}

那么算法是:

void quicksort_strs(char const *args[], unsigned int len)
{
    unsigned int i, pvt=0;

    if (len <= 1)
        return;

    // swap a randomly selected value to the last node
    swap_str_ptrs(args+((unsigned int)rand() % len), args+len-1);

    // reset the pivot index to zero, then scan
    for (i=0;i<len-1;++i)
    {
        if (strcmp(args[i], args[len-1]) < 0)
            swap_str_ptrs(args+i, args+pvt++);
    }

    // move the pivot value into its place
    swap_str_ptrs(args+pvt, args+len-1);

    // and invoke on the subsequences. does NOT include the pivot-slot
    quicksort_strs(args, pvt++);
    quicksort_strs(args+pvt, len - pvt);
}

那就是一切包括分区。

怎么运行的

有两种通用的递归快速排序算法:挤压扫描这是扫描算法。我们按顺序前进,将小于“小于”枢轴值(在循环开始前交换到序列末尾)的任何元素交换到目标位置,该位置的索引最初是序列的开始,并随着每个交换操作。完成“扫描”后,pvt索引就是枢轴所属的位置,因为该插槽下方的所有内容都“小于”该值。因此,又进行了一次交换以将枢轴值放入位置。之后,我们有两个分区,它们是递归的。包含在这些分区中的任何一个中。这是我们知道的唯一价值在于它的最终安息之地。

测试哈纳斯

包括上面的代码,我们用一组基本的字符串进行测试,这些字符串有意地乱序:

void print_list(char const *args[], unsigned len)
{
    unsigned i=0;
    for (;i<len;++i)
        puts(args[i]);
}

int main()
{
    char const *args[] =
    {
        "this", "is", "a", "test", "of", "quicksort", "with", "strings"
    };

    srand((unsigned)time(NULL));
    quicksort_strs(args, sizeof(args)/sizeof(*args));
    print_list(args, sizeof(args)/sizeof(*args));
    return 0;
}

输出

a
is
of
quicksort
strings
test
this
with

非递归实现

应当指出的是,上述算法使其本身精美的非递归实现。本地动态堆栈用于保存数据对:指针和长度。经过优化,不会将琐碎的段(长度为1或0的段)压入堆栈,一种实现方式是这样的:

void quicksort_strs(char const *args[], unsigned int len)
{
    // holds our non-recursive stack of segments
    struct segment
    {
        char const **arr;
        unsigned int len;
        struct segment* next;
    } *stack = NULL;

    stack = malloc(sizeof(*stack));
    stack->arr = args;
    stack->len = len;
    stack->next = NULL;

    while (stack != NULL)
    {
        unsigned int i, pvt=0;
        struct segment *tmp = stack;
        stack = stack->next;

        // pull values and delete segment record
        args = tmp->arr;
        len = tmp->len;
        free(tmp);

        // nothing to unary segments
        if (len <= 1)
            continue;

        // swap a randomly selected value to the last node
        swap_str_ptrs(args+((unsigned int)rand() % len), args+len-1);

        // reset the pivot index to zero, then scan
        for (i=0;i<len-1;++i)
        {
            if (strcmp(args[i], args[len-1]) < 0)
                swap_str_ptrs(args+i, args+pvt++);
        }

        // move the pivot value into its place
        swap_str_ptrs(args+pvt, args+len-1);

        // lhs segment push
        if (pvt > 1)
        {
            tmp = malloc(sizeof(*tmp));
            tmp->arr = args;
            tmp->len = pvt;
            tmp->next = stack;
            stack = tmp;
        }

        // rhs segment push
        if ((len - ++pvt) > 1)
        {
            tmp = malloc(sizeof(*tmp));
            tmp->arr = args+pvt;
            tmp->len = len-pvt;
            tmp->next = stack;
            stack = tmp;
        }
    }
}

显然,使用固定的节点堆栈实现将大大缩短此过程,但是这个想法应该显而易见。realloc()节点保存在“堆栈”末尾而不是开始的模式同样会很有趣,因为它将消除对next指针管理的需求,而将其替换为top索引。

无论如何,祝您好运,希望对您有所帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

关于C语言中的数组和字符串的困惑

来自分类Dev

比较C语言中的字符串数组

来自分类Dev

数组元素是C语言中字符串数组中的变量

来自分类Dev

字符串指针的C ++ Quicksort数组

来自分类Dev

如何在C语言中将无符号char数组转换为字符串?

来自分类Dev

在C语言中,如何从多维数组中打印字符串?

来自分类Dev

逐行将文件读取到C语言中的字符串数组中

来自分类Dev

如何在C语言中将无符号char数组转换为字符串?

来自分类Dev

`strcpy`超出了C语言中字符串数组的范围

来自分类Dev

在C语言中将“字符串”拆分为字符

来自分类Dev

在C语言中,如何找到字符串中的'\'字符?

来自分类Dev

关于C语言中的printf格式字符串

来自分类Dev

在C语言中为指针分配字符串

来自分类Dev

C语言中“字符串”的通用交换

来自分类Dev

递归C语言中的字符串计算器

来自分类Dev

在C语言中传递空字符串(“”)是否不好?

来自分类Dev

C语言中的字符串矩阵(类似于Matlab)

来自分类Dev

C语言中的字符串操作:这可能吗?

来自分类Dev

用用户输入操作C语言中的字符串

来自分类Dev

递归C语言中的字符串计算器

来自分类Dev

为什么在C语言中“字符串”被视为“常量”?

来自分类Dev

C语言中的结构和字符串

来自分类Dev

核心语言中的字符串比较

来自分类Dev

使用C语言中的“ sscanf”函数解析字符串中的子字符串

来自分类Dev

在C语言中,为什么在声明字符串后不能将其分配给char数组?

来自分类Dev

在C语言中,声明字符的二维数组或破烂的字符串数组是否更节省空间?(以下具体问题)

来自分类Dev

在字符串C语言中查找空格和字母数字字符

来自分类Dev

如何在C语言中的字符串中随机播放字符

来自分类Dev

在字符串数组上使用quicksort

Related 相关文章

  1. 1

    关于C语言中的数组和字符串的困惑

  2. 2

    比较C语言中的字符串数组

  3. 3

    数组元素是C语言中字符串数组中的变量

  4. 4

    字符串指针的C ++ Quicksort数组

  5. 5

    如何在C语言中将无符号char数组转换为字符串?

  6. 6

    在C语言中,如何从多维数组中打印字符串?

  7. 7

    逐行将文件读取到C语言中的字符串数组中

  8. 8

    如何在C语言中将无符号char数组转换为字符串?

  9. 9

    `strcpy`超出了C语言中字符串数组的范围

  10. 10

    在C语言中将“字符串”拆分为字符

  11. 11

    在C语言中,如何找到字符串中的'\'字符?

  12. 12

    关于C语言中的printf格式字符串

  13. 13

    在C语言中为指针分配字符串

  14. 14

    C语言中“字符串”的通用交换

  15. 15

    递归C语言中的字符串计算器

  16. 16

    在C语言中传递空字符串(“”)是否不好?

  17. 17

    C语言中的字符串矩阵(类似于Matlab)

  18. 18

    C语言中的字符串操作:这可能吗?

  19. 19

    用用户输入操作C语言中的字符串

  20. 20

    递归C语言中的字符串计算器

  21. 21

    为什么在C语言中“字符串”被视为“常量”?

  22. 22

    C语言中的结构和字符串

  23. 23

    核心语言中的字符串比较

  24. 24

    使用C语言中的“ sscanf”函数解析字符串中的子字符串

  25. 25

    在C语言中,为什么在声明字符串后不能将其分配给char数组?

  26. 26

    在C语言中,声明字符的二维数组或破烂的字符串数组是否更节省空间?(以下具体问题)

  27. 27

    在字符串C语言中查找空格和字母数字字符

  28. 28

    如何在C语言中的字符串中随机播放字符

  29. 29

    在字符串数组上使用quicksort

热门标签

归档