2012-03-29 111 views
1

我有以下数据结构:选择排序与链表的

struct scoreentry_node { 
    struct scoreentry_node *next; 
    int score; 
    char name[1];  
}; 
typedef struct scoreentry_node *score_entry; 

我想创建消耗,为了我的结构,安排他们根据名称升序排列的功能。我想修改的输入没有分配任何存储或释放任何东西:

我试过你的建议:

void selectionsort(score_entry *a) { 
    for (; *a != NULL; *a = (*a)->next) { 
     score_entry *minafteri = a; 
     // find position of minimal element 
     for (score_entry j = (*a)->next; j != NULL; j = j->next) { 
      if (strcmp(j->name, (*minafteri)->name) == -1) { 
       *minafteri = j; 
      } 
     } 
     // swap minimal element to front 
     score_entry tmp = *a; 
     a = minafteri; 
     *minafteri = tmp; 
    } 
} 

我与测试上面的代码如下:

score_entry x = add(8, "bob", (add(8 , "jill", (add (2, "alfred", NULL))))); 
iprint("",x); 
selectionsort(&x); 
iprint("", x); 
clear(x); //Frees the whole list 

iprint()在结构中打印分数和名称字段。我的添加功能如下:

score_entry add(int in, char *n, score_entry en) {  
    score_entry r = malloc(sizeof(struct scoreentry_node) + strlen(n)); 
    r->score = in; 
    strcpy(r->name, n); 
    r->next = en; 
    return r; 
} 

我得到堆错误,我的第二个打印不打印排序列表,它不打印任何东西。我做错了什么,我能做些什么来解决它?

+0

选择排序是单链表一个坏的排序算法(或列表一般,对于这个问题)。如果您正在寻找一种在运行时都是最优的排序算法,并且不分配任何内存,请尝试mergesort。 – Philip 2012-03-29 06:15:18

+0

'char name [1];'有点小。对于以空字符结尾的字符串,唯一有效的字符串将是“”,这将比较名称而非无用的。 – wildplasser 2012-03-29 10:42:59

+0

@Philip合并排序不会需要两个列表?我只有一个.. – Thatdude1 2012-03-29 15:21:43

回答

0

你必须参考传递参数selectionsort

void selectionsort(score_entry *a) { 
    for (; *a != NULL; *a = (*a)->next) 
    { 
     score_entry *minafteri = a; 
     // find position of minimal element 
     for (score_entry j = (*a)->next; j != NULL; j = j->next) { 
     if (strcmp(j->name, (*minafteri)->name) == -1) { 
     *minafteri = j; 
     } 
    } 
    // swap minimal element to front 
     score_entry tmp = *a; 
     a = minafteri; 
     *minafteri = tmp; 
    } 
} 
+0

嗯,我有typedef结构scoreentry_node * score_entry;它不是一个指向结构体的指针吗? – Thatdude1 2012-03-29 15:20:59

+0

@Beginnernato在这里你需要传递指针的引用,所以指向一个指针。 – 2012-03-29 15:29:39

+0

所以它需要在事端喜欢'selectionsort(&x)';其中x是指针结构?和我后,我打电话选择排序,x将排序? – Thatdude1 2012-03-29 15:48:41

1

除了通过地址传递指针(请参见下面的注释),您还需要修复您交换元素的方式太

void selectionsort(score_entry *a) { 
    for (; *a != NULL; *a = (*a)->next) 
    { 
    score_entry *minafteri = a; 
    // find position of minimal element 
    for (score_entry j = (*a)->next; j != NULL; j = j->next) { 
     if (strcmp(j->name, (*minafteri)->name) == -1) { 
     *minafteri = j; 
     } 
     } 
    // swap minimal element to front 
    score_entry tmp = *a; 
    a = minafteri; // put the minimal node to current position 
    tmp->next = (*a)->next ; //fix the links 
    (*minafteri)->next=tmp; //fix the links 
    } 
} 
+0

请注意,通过引用不严格地存在于C中。您传递一个值(指针)并取消引用指针。 http://stackoverflow.com/questions/2229498/passing-by-reference-in-c“> – Chris 2012-03-29 06:56:32

+0

@chirs oops我的坏编辑答案 – keety 2012-03-29 07:04:59

+0

这个解决方案是坏的:'* a =(* a) - > next' - >'a =&(* a) - > next',并且由于您没有更新从前一个节点到您移动的链接的链接,因此该列表仍然损坏。 – chqrlie 2017-08-13 19:18:18

0

这段代码很可怕!您不仅没有向我们提供重现您的问题的所有必需品(我们无法编译这个!),但您已经隐藏了指针抽象背后的typedef(对我们来说也是一场噩梦)。一般来说,一个甚至不应该在C使用链表了别说排序他们...

但是,这里有两个答案。


*minafteri = j;发现在您找到循环实际修改您的列表!为什么你的找到循环正在修改你的列表?

答案:它不应该!通过而不是分配minafteri = &j->next,你将不会被修改清单,你发现环......


或者,您可以执行环路内的交换。

*minafteri = j;将需要交换以下,顺序如下:

  • (*minafteri)->nextj->next
  • *minafterij

你认为一行代码能够执行那些两次掉期?好吧,它通过其中一个中途...并在过程中从您的列表中删除一堆元素!


下似乎是一个错误的尝试交换元素:

score_entry *minafteri = a; // half of assigning `a` to `a` 
/* SNIP! 
* Nothing assigns to `minafteri` in this snippet. 
* To assign to `minafteri` write something like `minafteri = fubar;` */ 
score_entry tmp = *a;  // half of assigning `*a` to `*a` 
a = minafteri;    // rest of assigning `a` to `a` 
*minafteri = tmp;   // rest of assigning `*a` to `*a` 

它真的只是分配*a*aaa ...你认为你需要做的是什么?

我以为你会注意到当你创建你的MCVE ......哦,等一下!真丢脸!


专注于交换列表中的两个节点作为较小的任务。一旦你做完了,考虑完成这个任务。

0

有你的代码中的多个问题:

  • if (strcmp(j->name, (*minafteri)->name) == -1) {是不正确的:strcmp()不一定返回-1,当第一个字符串小于第二,它可以返回任何负值。
  • 您调整链接以移动较低条目的方式不正确:您无法更新从前一个节点到您移动到起始节点的链接。该列表已损坏。

这里是一个改进版本:

void selectionsort(score_entry *a) { 
    for (; *a != NULL; a = &(*a)->next) { 
     // find position of minimal element 
     score_entry *least = a; 
     for (score_entry *b = &(*a)->next; *b != NULL; b = &(*b)->next) { 
      if (strcmp((*b)->name, (*least)->name) < 0) { 
       least = b; 
      } 
     } 
     if (least != a) { 
      // swap minimal element to front 
      score_entry n = *least; 
      *least = n->next; /* unlink node */ 
      n->next = *a;  /* insert node at start */ 
      *a = n; 
     } 
    } 
}