按字母顺序排序双向链表
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;
当我 运行 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;
}
任务是按字母顺序对列表进行排序。这将通过更改指针变量来完成,而不仅仅是切换节点的内容。
我首先想实现一个交换功能。该功能应交换 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;
当我 运行 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;
}