[英]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.