[英]Quicksort of Linked List in C
好的,在使用gdb和valgrind失敗之后,我謙虛地向您提出了我的問題。 我們被要求使用列表中的第一個元素作為樞紐,以c語言實現quicksort的版本(以保持與本學期早些時候完成的簡單haskell實現的可比性)。 提供了LIST實現(制作,打印和結構定義),其余的工作由我們決定。 我(感到驚訝)感到異常,但是valgrind出現了大量錯誤以及堆棧溢出,因此也許有些新鮮的眼睛可以對我有所幫助。
我的代碼:
#include <stdio.h>
#include <stdlib.h>
typedef struct CELL *LIST;
struct CELL {
int element;
LIST next;
};
LIST MakeList();
void PrintList(LIST);
LIST qSort(LIST);
int listLength(LIST);
LIST combine(LIST, LIST, LIST);
int main(){
LIST list;
printf ("enter a several numbers separated by spaces or returns and ended by Ctrl-D\n");
list = MakeList();
PrintList(qSort(list));
return 0;
}
LIST qSort(LIST list){
LIST current, pivot = list, temp = NULL;//use first element as pivot, start comparison at list->next
LIST little, big, littleHead, bigHead;
little = (LIST) malloc(sizeof(struct CELL));
little->element = 0;
little->next = NULL;
littleHead = little;
big = (LIST) malloc(sizeof(struct CELL));
big->element = 0;
big->next = NULL;
bigHead = big;
if(listLength(list) <= 1){//base case
return list;
}
//remove pivot by setting current to list->next
current = list->next;
do{
if(current->element <= pivot->element){
little->element = current->element;
little->next = (LIST) malloc(sizeof(struct CELL));
little = little->next;
little->next = NULL;
}
else{
big->element = current->element;
big->next = (LIST) malloc(sizeof(struct CELL));
big = big->next;
big->next = NULL;
}
current = current->next;
}while(current != NULL);
littleHead = qSort(littleHead);
bigHead = qSort(bigHead);
return combine(littleHead, bigHead, pivot);
}
int listLength(LIST list){
int length = 0;
LIST current = list;
if(NULL==list){
return length;
}
else{
while(current != NULL){
current = current->next;
length++;
}
}
return length;
}
LIST combine(LIST little, LIST big, LIST pivot){
LIST temp = little;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = pivot;
pivot->next = big;
return little;
}
LIST MakeList()
{
int x;
LIST pNewCell;
if (scanf("\%d", &x) == EOF) return NULL;
else {
pNewCell = (LIST) malloc(sizeof(struct CELL));
pNewCell->next = MakeList();
pNewCell->element = x;
return pNewCell;
}
}
void PrintList(LIST list)
{
while (list != NULL) {
printf("\%d\n", list->element);
list = list->next;
}
}
和valgrind輸出
==20391== Conditional jump or move depends on uninitialised value(s)
==20391== at 0x804855D: qSort (2100assignment4.c:45)
==20391== by 0x80485E0: qSort (2100assignment4.c:61)
==20391== by 0x80484BD: main (2100assignment4.c:22)
==20391== Uninitialised value was created by a heap allocation
==20391== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20391== by 0x8048574: qSort (2100assignment4.c:47)
==20391== by 0x80484BD: main (2100assignment4.c:22)
==20391==
==20391== Conditional jump or move depends on uninitialised value(s)
==20391== at 0x804855D: qSort (2100assignment4.c:45)
==20391== by 0x80485E0: qSort (2100assignment4.c:61)
==20391== by 0x80485E0: qSort (2100assignment4.c:61)
==20391== by 0x80484BD: main (2100assignment4.c:22)
==20391== Uninitialised value was created by a heap allocation
==20391== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20391== by 0x8048574: qSort (2100assignment4.c:47)
==20391== by 0x80484BD: main (2100assignment4.c:22)
==20391==
==20391== Conditional jump or move depends on uninitialised value(s)
==20391== at 0x804855D: qSort (2100assignment4.c:45)
==20391== by 0x80485E0: qSort (2100assignment4.c:61)
==20391== by 0x80485E0: qSort (2100assignment4.c:61)
==20391== by 0x80485E0: qSort (2100assignment4.c:61)
==20391== by 0x80484BD: main (2100assignment4.c:22)
==20391== Uninitialised value was created by a heap allocation
==20391== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20391== by 0x8048574: qSort (2100assignment4.c:47)
==20391== by 0x80485E0: qSort (2100assignment4.c:61)
==20391== by 0x80484BD: main (2100assignment4.c:22)
==20391==
==20391== Stack overflow in thread 1: can't grow stack to 0xbe297ff4
==20391==
==20391== Process terminating with default action of signal 11 (SIGSEGV)
==20391== Access not within mapped region at address 0xBE297FF4
==20391== at 0x402BE35: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20391== If you believe this happened as a result of a stack
==20391== overflow in your program's main thread (unlikely but
==20391== possible), you can try to increase the size of the
==20391== main thread stack using the --main-stacksize= flag.
==20391== The main thread stack size used in this run was 8388608.
==20391== Stack overflow in thread 1: can't grow stack to 0xbe297fe4
==20391==
==20391== Process terminating with default action of signal 11 (SIGSEGV)
==20391== Access not within mapped region at address 0xBE297FE4
==20391== at 0x4025430: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-x86-linux.so)
==20391== If you believe this happened as a result of a stack
==20391== overflow in your program's main thread (unlikely but
==20391== possible), you can try to increase the size of the
==20391== main thread stack using the --main-stacksize= flag.
==20391== The main thread stack size used in this run was 8388608.
==20391==
==20391== HEAP SUMMARY:
==20391== in use at exit: 4,190,952 bytes in 523,869 blocks
==20391== total heap usage: 523,869 allocs, 0 frees, 4,190,952 bytes allocated
==20391==
==20391== LEAK SUMMARY:
==20391== definitely lost: 0 bytes in 0 blocks
==20391== indirectly lost: 0 bytes in 0 blocks
==20391== possibly lost: 0 bytes in 0 blocks
==20391== still reachable: 4,190,952 bytes in 523,869 blocks
==20391== suppressed: 0 bytes in 0 blocks
==20391== Rerun with --leak-check=full to see details of leaked memory
==20391==
==20391== For counts of detected and suppressed errors, rerun with: -v
==20391== ERROR SUMMARY: 261929 errors from 3 contexts (suppressed: 0 from 0)
首先要解決的一些問題:
if (scanf("\%d", &x) == EOF) return NULL;
不需要\\。 檢查!= 1可能會更容易,因為您期望一個值。
這導致您的MakeList無限遞歸(至少在我的機器上)。
在您的qsort函數中,小列表和大列表始終在末尾有一個虛擬條目-通過此代碼完成
little->next = (LIST) malloc(sizeof(struct CELL));
little = little->next;
little->next = NULL;
這意味着,當您拆分列表時,最終得到的條目總是比開始時要多,因此它永遠都不會結束。 還要注意,這些新條目未設置其元素值,這可能是您收到未初始化警告的地方。
您應該重新考慮如何存儲子列表,也許以NULL開頭,以指示為空,盡管這會使添加新值變得更加困難。
您可以按以下方式編輯清單列表功能。
您將觀察到一些變化。
scanf
通過刪除\\
是正確的(請參閱《黑暗的答案》)scanf
讀取時,如果您輸入任何不兼容的輸入(例如字母)而不是Ctrl + D,這將確保讀取停止。
LIST MakeList()
{
int x;
LIST pNewCell;
while(scanf("%d", &x))
{
pNewCell = (LIST) malloc(sizeof(struct CELL));
pNewCell->next = MakeList();
pNewCell->element = x;
return pNewCell;
}
return NULL;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.