【问题标题】:quicksort with linked lists带链表的快速排序
【发布时间】:2012-03-14 11:57:01
【问题描述】:

我编写了以下程序,该程序使用快速排序算法对使用链表将多少整数放入命令行进行排序。我不仅收到关于混合声明的 ISO C90 错误,而且我的代码中的某处存在内存泄漏,我不知道如何修复它。任何帮助将不胜感激!

#include <stdio.h>
#include "linked_list.h"
#include <stdlib.h>
#include "memcheck.h"
#include <string.h>
#include <assert.h>

node *quicksort(node *list);
int ListLength (node *list);

int main(int argc, char *argv[]) {
    if (argc == 1) {
    fprintf(stderr, "usage: %s [-q] number1 number2 ... \
    (must enter at least one argument)\n", argv[0]);
    exit(1);
    }
    node *list;
    node *sorted_list;
    int i;
    int intArg = 0; /* number of integer arguments */
    int print = 1;
    /* if -q is found anywhere then we are going 
     * to change the behavior of the program so that
     * it still sorts but does not print the result */
    for ( i = 1 ; i < argc; i++) {
        if (strcmp(argv[i], "-q") == 0) {
            print = 0;
        }
        else {
            list = create_node(atoi(argv[i]), list); /* memory allocation in the           create_node function */
            intArg++; }
    }

    if (intArg == 0) {
        fprintf(stderr, "usage: %s [-q] number1 number2 ...\
       (at least one of the input arguments must be an integer)\n", argv[0]); 
        exit(1); }
    sorted_list = quicksort(list);
    free_list(list);
    list = sorted_list;
    if (print == 1) {
        print_list(list); }
    print_memory_leaks();
    return 0; } 

/* This function sorts a linked list using the quicksort
 * algorithm */
node *quicksort(node *list) {
node *less=NULL, *more=NULL, *next, *temp=NULL, *end;
node *pivot = list;
if (ListLength(list) <= 1) {
    node *listCopy;
    listCopy = copy_list(list);
    return listCopy; }
else {
    next = list->next;
    list = next;
    /* split into two */
    temp = list;
    while(temp != NULL) {
        next = temp->next;
        if (temp->data < pivot->data) {
            temp->next = less;
            less = temp;
   }
        else {
            temp->next = more;
            more = temp;
  }
        temp = next;
  }
    less = quicksort(less);
    more = quicksort(more); }
   /* appending the results */
if (less != NULL) {
    end = less;
    while (end->next != NULL) {
        end = end->next;
  } 
pivot->next = more;
end->next = pivot;
return less; }
else {
    pivot->next = more;
return pivot; } } 
int ListLength (node *list) {
    node *temp = list;
    int i=0;
    while(temp!=NULL) {
        i++; 
        temp=temp->next; }
return i; }

【问题讨论】:

  • 什么是编译器错误信息?你怎么知道有内存泄漏?
  • 它从分配内存开始,然后以正确的顺序打印我输入的几个数字,但停止并打印内存泄漏 line:78 ,然后在第 20 行打印了很多次。
  • 混合声明错误可能归结为在声明变量之前检查 argc。如果我在 gcc 中使用 -pedantic 标志进行编译,我会得到这个。
  • 解决了这个问题,谢谢!但是,代码仍然无法正常工作。
  • create_node 的代码在哪里?

标签: c sorting linked-list quicksort


【解决方案1】:

main,你释放了一个节点,即链表的原始头:

sorted_list = quicksort(list);
free_list(list);

但是你永远不会释放任何其他节点,尽管你复制了节点。因此,从第一个保存的所有原始列表节点都浮动在无法访问的内存中。 free 复制,然后不要 free 复制 main,或者根本不复制(释放 main 中的所有节点,但仅在您不再需要它们之后)。

【讨论】:

  • 你不正确。 main 中唯一的另一个节点是 sorted_list,它在释放时没有解决问题。
  • 我希望list = create_node(atoi(argv[i]), list); 分配节点,尤其是考虑到该行的注释。在 main 中,除了其中一个(可能是排序后的两个)之外,您永远不会直接引用它们中的任何一个。然后在quicksortcopy_list 当你达到长度1的节点,忘记原来的节点。因此,您从原始未被释放(并且通常很快变得无法访问)的复制节点组装排序列表。此外,list 指向原始头部,即第一个枢轴。枢轴不会被复制,因此它是排序列表的一部分。 ...
  • 当你free它时,你会撕裂排序列表,它的前身现在有一个悬空指针,并且它后面的节点不再可访问(但你可能不会注意到,如果它从未被覆盖)。
【解决方案2】:

好吧,你还没有发布 free_list()create_node() 的代码,它们是潜在内存泄漏的主要候选者,但我相信你的 quicksort() 代码在这里有内存泄漏:

    less = quicksort(less);
    more = quicksort(more); }

如果任一列表只有一个元素,则此代码:

if (ListLength(list) <= 1) {
    node *listCopy;
    listCopy = copy_list(list);
    return listCopy; }

返回一个元素的副本。通过在此处设置lessmore 指针,您可能会丢失一个节点。

考虑一下列表:2 1 3

代码会将1 添加到less 列表中,并将3 添加到more 列表中。然后它会对这两个单元素列表执行quicksort(),返回列表的副本,并丢失指向原始lessmore 列表的指针,从而导致两个节点的内存泄漏。

巧合的是,最好将上面if语句的检查替换为:

if (list == NULL || list->next == NULL) {

这避免了必须遍历一个可能很长的列表来检查它是否只包含 0 或 1 个元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 2018-11-06
    • 2013-01-26
    相关资源
    最近更新 更多