当处理大小大于5000的双链表时,出现堆栈溢出错误。我的算法为每个递归创建了双链表的2个新对象,这些对象在每次递归后追加到排序列表中。有没有其他方法可以创建对象,这样我就不必在每次快速排序递归中都这样做?
static void quick_sort(List sortList, Node first, Node last)
{
//Quick sort algorithm
Node left, pivNode;
List bigList = new List();
List endList = new List();
int pivot;
pivNode = first; //Sets node to become pivot (1st node in given range)
left = first.next; //Sets comparison node
pivot = first.data; //Sets integer for pivot
if (last.next != null)
{
//Creates a new list if there are nodes after last node
endList.firstNode = last.next;
last.next = null;
endList.firstNode.prev = null;
}
if (left != null)
{
do
{
if (left.data > pivot)
{
Node popNode;
popNode = left;
removeNode(popNode, sortList); //Removes node larger than pivot from sortList
left = pivNode; //Resets left node to pivNode
if (bigList.firstNode == null) //Inserts larger node into bigList
{
insertBeginning(popNode, bigList);
}
else
{
popNode.next = popNode.prev = null;
insertEnd(popNode, bigList);
}
}
if (left.data <= pivot)
{
swapNode(left, pivNode); //Swaps smaller node with pivNode(moves smaller nodes to left of list)
pivNode = left; //Resets pivNode to correct node
}
left = left.next;
} while (left != last.next); //Iterates until last given node
}
if (endList.firstNode != null)
{
//If endList exists
if (bigList.firstNode != null)
{
//If bigList exists
appendLists(bigList, endList); //Appends endList at end of bigList
}
else
{
//If bigList doesn't exist, changes it to endList
bigList = endList;
}
}
appendLists(sortList, bigList); //Appends bigList to end of sortList
if (endList.firstNode != null)
{
last = endList.firstNode.prev; //Set's correct last node
}
//Recursion until last has been fully sorted
if (pivNode.prev != first && pivNode != first)
{
quick_sort(sortList, first, pivNode.prev);
}
if (pivNode != last && first != last)
{
quick_sort(sortList, pivNode.next, last);
}
}
答案 0 :(得分:0)
为防止堆栈溢出,请创建两个计数器,它们的名称分别为left_counter和right_counter。在分区步骤中,更新计数器,以使left_counter =从第一个到透视图或ivot.prev的节点数,而right_counter是从第一个透视图或pivot.next到最后一个节点的数。比较两个计数器,并在对应于较小计数的子列表上使用递归。然后根据要排序的部分(通过递归)更新first = pivot.next或last = pivot.prev,然后循环回到代码顶部以继续。
在排序过程中,创建循环的双向链接列表可能会更简单,因此first.prev指向最后一个节点,last.next指向第一个节点。这样一来,在交换第一个或最后一个节点或附近的节点时,不必检查是否为空。
该代码显示使用名为List的类类型,但通常是C#的本机类,具有对“列表”中的元素进行索引(随机访问)的能力,类似于数组。列表类可能应使用其他名称,双向链接列表应使用“ DLList”。