选择排序与链表

时间:2012-03-29 06:07:34

标签: c sorting linked-list structure

我有以下数据结构:

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;   
}

我收到堆错误,我的第二个打印不会打印排序列表,它什么都不打印。我做错了什么,我该怎么做才能解决它?

5 个答案:

答案 0 :(得分: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
  }
}

答案 1 :(得分: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;
  }
}

答案 2 :(得分:0)

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

尽管如此,这里有两个答案。

find 循环中找到的

*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分配给*aa分配给a ......你认为你需要这样做吗?

当你创建MCVE时,我以为你会注意到那个 ......哦,等一下!对你感到羞耻!

专注于将列表中的两个节点交换为较小的任务。完成后,请考虑承担此任务。

答案 3 :(得分: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;
        }
    }
}

答案 4 :(得分:0)

这是链表上选择排序的Java实现:

  
      
  • 时间复杂度:O(n ^ 2)
  •   
  • 空间复杂度:O(1)-选择排序是就地排序算法
  •   
class Solution 
{
    public ListNode selectionSortList(ListNode head)
    {
        if(head != null)
        {
            swap(head, findMinimumNode(head));
            selectionSortList(head.next);
        }
        return head;
    }

    private void swap(ListNode x, ListNode y)
    {
        if(x != y)
        {
            int temp = x.val;
            x.val = y.val;
            y.val = temp;    
        }
    }

    private ListNode findMinimumNode(ListNode head)
    {
        if(head.next == null)
            return head;

        ListNode minimumNode = head;

        for(ListNode current = head.next; current != null; current = current.next)
        {
            if(minimumNode.val > current.val)
                minimumNode = current;
        }
        return minimumNode;
    }
}