java快速排序引起的StackOverflowError异常
写在前面:这篇随笔主要记录一下递归调用引起的虚拟机栈溢出的情况以及通过参数配置了虚拟机栈大小来使递归调用可以顺利执行。并没有对涉及到的一些概念进行详细的解释(因为我自己目前对这些概念并不是特别清楚),可以用于参考的关键字:
关键字:java虚拟机栈,栈溢出,栈帧
今天在对比快速排序与冒泡排序时,通过代码分别实现了最简单的快速排序与冒泡排序(从小到大排序),代码如下:
1 /** 2 * 冒泡排序 3 */ 4 5 public class BubbleSortDemo { 6 public static void main(String[] args) { 7 int[] nums = new int[100000]; 8 for (int i = nums.length - 1, j = 0; i >= 0; i--, j++) { 9 nums[j] = i; 10 } 11 long start = System.currentTimeMillis(); 12 bubbleSort(nums); 13 long end = System.currentTimeMillis(); 14 System.out.println((end - start) + "ms"); 15 } 16 17 public static void bubbleSort(int[] nums) { 18 int swapCount = -1; 19 while (swapCount != 0) { 20 swapCount = 0; 21 for (int i = 0; i < nums.length - 1; i++) { 22 int iItem = nums[i]; 23 int jItem = nums[i + 1]; 24 if (iItem > jItem) { 25 swap(nums, i, i + 1); 26 swapCount++; 27 } 28 } 29 } 30 } 31 32 /** 33 * 交换数组nums[]中i和j位置的两个元素 34 */ 35 public static void swap(int[] nums, int i, int j) { 36 int temp = nums[i]; 37 nums[i] = nums[j]; 38 nums[j] = temp; 39 } 40 }
1 /** 2 * 快速排序 3 */ 4 5 public class QuickSortDemo { 6 public static void quickSort(int[] nums, int leftIndex, int rightIndex) { 7 if (nums.length <= 1 || leftIndex >= rightIndex) { 8 return; 9 } 10 11 int pivot = nums[leftIndex]; 12 int left = leftIndex; 13 int right = rightIndex; 14 15 while (left < right) { 16 while (left < right && nums[right] >= pivot) { 17 right --; 18 } 19 if (left < right) { 20 nums[left] = nums[right]; 21 left ++; 22 } 23 while (left < right && nums[left] <= pivot) { 24 left ++; 25 } 26 if (left < right) { 27 nums[right] = nums[left]; 28 right --; 29 } 30 } 31 nums[left] = pivot; 32 quickSort(nums, leftIndex, left - 1); 33 quickSort(nums, left + 1, rightIndex); 34 } 35 36 public static void quickSort(int[] nums) { 37 if (nums != null) { 38 quickSort(nums, 0, nums.length - 1); 39 } 40 } 41 42 public static void main(String[] args) { 43 int[] nums = new int[100000]; 44 for (int i = nums.length - 1, j = 0; i >= 0; i--, j++) { 45 nums[j] = i; 46 } 47 long start = System.currentTimeMillis(); 48 quickSort(nums); 49 long end = System.currentTimeMillis(); 50 System.out.println((end - start) + "ms"); 51 } 52 53 }
在它们的main函数中,我生成了length=100000的从大到小排列的有序数组对两个排序算法进行测试,观察它们的执行时间。
对于冒泡排序,对100000个有序数组进行排序,花费了12833ms。
对于快速排序,对100000个有序数组进行排序,因为快速排序采用了递归来实现,程序抛出了StackOverflowError异常,本来以为是哪个地方陷入了死循环导致的,后来经过排查,其实是因为虚拟机栈溢出,函数调用的太深了。通过设置虚拟机参数-Xss10m,为虚拟机栈分配了10M的内存,使这个算法可以正常执行。最后,快速排序花费了4830ms。