簡體   English   中英

按字母順序排序雙向鏈表

[英]Sorting doubly linked list alphabetical

任務是按字母順序對列表進行排序。 這是通過改變指針變量而不是僅僅切換節點的內容來完成的。

我首先想實現一個交換功能。 該函數應交換 2 個節點。 之后我想實現一個排序算法。 我的問題是,交換函數並沒有真正發揮應有的作用,算法也沒有(ofc,因為交換函數甚至不起作用)。

    struct student {
      char Vorname[51];
      char Nachname[51];
      int MatNr;
      char Adresse[51];
      int Kurse;
      struct student *next;
      struct student *previous;
    };

    struct student *first = NULL;
    struct student *last = NULL;  

    void swap(struct student *pointer) {
      struct student *pointer1, *pointer3, *pointer4;
      pointer1 = pointer->previous;
      pointer3 = pointer->next;
      pointer4 = pointer->next->next;

      pointer4->previous = pointer;
      pointer->next = pointer4;
      pointer1->next = pointer3;
      pointer3->previous = pointer1;
      pointer->previous = pointer3;
      pointer3->next = pointer;
    }

這是未完成的排序功能。 我還沒有正確實現它,因為交換功能首先引起了我的注意。

void sort(void) {
  struct student *pointer1, *pointer2, *pointer3, *pointer4;
  pointer1 = first->previous;
  pointer2 = pointer1->next;
  pointer3 = pointer2->next;
  pointer4 = pointer3->next;

  while(pointer2 != NULL){
    if((strcmp(pointer2->Nachname, pointer3->Nachname)) > 0) {
           swap(pointer2);
    }
    pointer1 = pointer1->next;
    printList();
  }
}  

當我運行swap(first); 由於指針的第一個元素犯規得到顯示first現在指向第二個節點。 好吧,這很容易用first = pointer3;完成first = pointer3;

當我運行swap(first->next); 有一個類似的問題,因為它也遺漏了列表的一個節點。

我不太確定如何正確使用此功能,因為first不應該參與交換列表的第二個和第三個節點。

我很感激任何可以幫助我解決這個問題的幫助,也許我只是忽略了一些小錯誤,但我真的無法解決這個問題。 謝謝!

通過交換雙向鏈接節點對列表進行排序似乎效率很低,因為您不能使用諸如歸並排序之類的快速算法。

您可以改為僅使用遞歸合並排序函數中的next鏈接,並在結果列表上重建后向鏈接。

這是如何做到的:

struct student {
    char Vorname[51];
    char Nachname[51];
    int MatNr;
    char Adresse[51];
    int Kurse;
    struct student *next;
    struct student *previous;
};

struct student *first = NULL;
struct student *last = NULL;

/* Merge two sorted lists. p1 and p2 are != NULL */
struct student *merge(struct student *p1, struct student *p2) {
    struct student *head, **pp;
    pp = &head;
    for (;;) {
        if (strcmp(p1->Nachname, p2->Nachname) <= 0) {
            *pp = p1;
            pp = &p1->next;
            p1 = p1->next;
            if (p1 == NULL) {
                *pp = p2;
                break;
            }
        } else {
            *pp = p2;
            pp = &p2->next;
            p2 = p2->next;
            if (p2 == NULL) {
                *pp = p1;
                break;
            }
        }
    }
    return head;
}

/* Recursive top-down merge sort */
struct student *msort(struct student *np) {
    struct student *p1, *p2;
    /* trivial lists are sorted */
    if (np == NULL || np->next == NULL)
        return np;
    /* locate mid-point using 2 finger method */
    for (p1 = np, p2 = np->next; p2 && p2->next; p2 = p2->next->next)
        p1 = p1->next;
    /* split the list at mid-point */
    p2 = p1->next;
    p1->next = NULL;
    p1 = np;
    /* sort the sublists recursively */
    p1 = msort(p1);
    p2 = msort(p2);
    return merge(p1, p2);
}

void sort(void) {
    struct student *p1, *p2;
    /* sort the list as a singly linked list */
    first = msort(first);
    /* reconstruct the backlinks */
    p1 = NULL;
    for (p2 = first; p2; p2 = p2->next) {
        p2->last = p1;
        p1 = p2;
    }
    last = p1;
}

正如rcgldr所建議的那樣,使用自下而上的歸並排序來避免重復掃描列表可能更有效。 這是替代代碼:

/* bottom-up merge sort with sublist array */
struct student *msort(struct student *head) {
    struct student *array[32] = { NULL };
    int i;

    /* handle trivial lists */
    if (head == NULL || head->next == NULL)
        return head;

    i = 0;  /* avoid warning */
    p1 = head;
    /* merge nodes into pending lists of increasing lengths */
    while (head != NULL) {
        struct student *next = head->next;
        head->next = NULL;
        for (i = 0; i < 32 && array[i] != NULL; i++) {
            head = merge(array[i], head);
            array[i] = NULL;
        }
        /* do not go past end of array */
        if (i == 32)
            i--;
        array[i] = head;
        head = next;
    }
    /* merge pending lists into single list:
     * the last element stored into the array is at offset i and
     * all entries before it are NULL pointers. */
    for (head = array[i++]; i < 32; i++) {
        if (array[i] != NULL)
            head = merge(array[i], head);
    }
    return head;
}

暫無
暫無

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

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