簡體   English   中英

選擇排序與鏈表的

[英]Selection sort with linked list's

我有以下數據結構:

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

我遇到堆錯誤,第二張打印不打印排序列表,什么也不打印。 我在做什么錯,該怎么解決?

除了按地址傳遞指針(請參閱下面的注釋)之外,您還需要修復交換元素的方式

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

此代碼是可怕的! 您不僅沒有為我們提供重現問題的所有必要條件(我們無法編譯該問題!),而且還隱藏了typedef背后的指針抽象(這也是我們的噩夢)。 一般來說,甚至不應該再使用 C中的鏈表了,更不用說它們進行排序了。

但是,這里有兩個答案。


*minafteri = j; 在您的查找循環中找到的內容實際上會修改您的列表! 為什么您的查找循環應修改列表?

答:不應該! 通過分配minafteri = &j->next ,您將不會使用find循環修改列表...


或者,您可以在該循環內執行交換。

*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 ......喔,等一下! 你太無恥了!


專注於交換列表中的兩個節點作為較小的任務。 完成此操作后,請考慮執行此任務。

您的代碼中存在多個問題:

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

這是鏈表上選擇排序的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;
    }
}

您必須通過引用將參數傳遞給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;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM