记录:列表排序(二)

匿名 (未验证) 提交于 2019-12-03 00:29:01

文章来源――JAVA程序员成功面试秘籍

  1. 冒泡排序。效率低,最坏情况性能是O(n*n),最好情况性能是O(n)。
//伪代码 for i between 0 and (array length-2)     if(array[i+1]<array[i])         交换array[i]和array[i+1] 一直重复,直到在一次完整的迭代中没有元素被交换  //冒泡排序例子 public void bubbleSort(int[] numbers){     boolean numbersSwitched;     do{         numberSwitched = false;         for(int i = 0; i < numbers.length - 1 ; i++){             if(numbers[i+1] < numbers[i]){                 int temp = numbers[i+1];                 numbers[i+1] = numbers[i];                 numbers[i] = temp;                  numbersSwitched = true;             }         }     }while(numbersSwitched); }
    2. 插入排序算法返回值是一个新的List,而且是链表LinkedList的实例。链表类型的列表在中间插入元素比较 高效,而ArrayList内部实现的是数组,如果从表头或中间插入要不断地移动元素,代价高。最坏情况复杂度为O(n*n),最好情况复杂度为O(n)。
//伪代码 给定列表l和新列表nl for each element originallistelemin list l:     for each element newlistelemin list nl:         if(originallistelem < newlistelem):             originallistelem插入nl中在newlistelem之前的位置         else:             继续下一个元素     if originallistelem没有被插入:         插入nl的尾端  //插入排序实例 public static List<Integer> insertSort(final List<Integer> numbers){     final List<Integer> sortedList = new LinkedList<>();     originalList: for (Integer number : numbers){         for(int i=0; i<sortedList.size(); i++){             if(number < sortedList.get(i)){                 sortedList.add(i,number);                 continue originalList;             }         }         sortedList.add(sortedList.size(),number);     }     return sortedList; }

    3. 快速排序(quicksort)算法这个算法是递归的。性能远高于冒泡和插入排序,最坏情况的复杂度任然是O(n*n),平均复杂度是O(n log n)。基础情形是列表里有0个和1个元素,此时直接返回。第二部分是从列表中任意挑选出一个元素为枢轴(pivot),剩下的元素分两组:一组中的元素比枢轴小,另一组大于等于枢轴。然后针对这两个列表调用此方法,返回的结果是两个排好序的列表。

//伪代码 method quicksort(list l):     if l.size < 2:         return l     let pivot = l(0)     let lower = new list     let higher = new list     for each element e in between l(0) and the end of the list:         if e < pivot:             add e to lower         else add e to higher     let sortedlower = quicksort(lower)     let sortedhigher = quicksort(higher)     return sortedlower + pivot + sortedhigher  //快速排序实例 public static List<Integer> quicksort(List<Integer> numbers){     if(numbers.size() < 2){         return numbers;     }     final Integer pivot = numbers.get(0);//取第一个元素为枢轴,亦可取其他元素     // 提取出的枢轴是否不放入这两个列表中?     final List<Integer> lower = new ArrayList<>();     final List<Integer> higher = new ArrayList<>();     for(int i = 1; i <numbers.size(); i++){         if(numbers.get(i) < pivot){             lower.add(numbers.get(i));         }else{             higher.add(numbers.get(i));         }     }     // 每一次对列表的分割和后续的递归调用都是互相无关的,因此可以并行执行     final List<Integer> sorted = quicksort(lower);     sorted.add(pivot);     sorted.addAll(quicksort(higher));     return sorted; } 

    4. 归并排序算法又是一个分而治之(divide-and-conquer)的算法,将列表分为两个子列表,分别对这两个列表进行排序,然后将两个子列表归并为一个列表。算法复杂度为O(n log n),即每一个合并操作的复杂度为O(n),而每一次递归调用都只针对给定列表的一半进行操作。List类的subList方法接受两个参数:from 和 to,其中from 是包括的,to 是不包括的。

//伪代码 method mergesort(list l):     if list.size < 2:         return l     let middleIndex = l.size / 2      let leftList = elements between l(0) and l(middleIndex - 1)     let rightList = elements between l(middleIndex) and l(size - 1)     let sortedLeft = mergesort(leftList)     let sortedRight = mergesort(rightList)     return merge(sortedLeft, sortedRight) method merge(list l, list r)     let leftPtr = 0     let rightPtr = 0     let toReturn = new list     while (leftPtr < l.size and rightPtr < r.size):         if(l(leftPtr) < r(rightPtr)):             toReturn.add(l(leftPtr)):             leftPtr++         else:             toReturn.add(r(rightPtr))             rightPtr++     while(leftPtr < l.size):         toReturn.add(l(leftPtr))         leftPtr++     while(rightPtr < r.size):         toReturn.add(r(rightPtr))         rightPtr++     return toReturn  //归并排序实例 public static List<Integer> mergesort(final List<Integer> values){     if(values.size() < 2){         return values;     }     final List<Integer> leftHalf = values.subList(0, values.size() / 2);     final List<Integer> rightHalf = values.subList(values.size() / 2, values.size());     //递归拆分排序合并     return merge(mergesort(leftHalf), mergesort(rightHalf)); } //merge方法:合并两个已排好序的列表 private static List<Integer> merge(final List<Integer> left, final List<Integer> right){     int leftPtr = 0;     int rightPtr = 0;     final List<Integer> merged = new ArrayList<>(left.size() + right.size());     //选择两个指针指向的值中最小的那个值,将这个值添加到结果列表中,然后递增相应的指针。有一个指针到达其对应的列表尾端时,将另一个列表后面剩下的部分全部添加到结果列表中。     while(leftPtr < left.size() && rightPtr < right.size()){         if(left.get(leftPtr)<right.get(rightPtr)){             merged.add(left.get(leftPtr));             leftPtr++;         }else{             mergeed.add(right.get(rightPtr));             rightPtr++;         }     }     //下面两个while循环的条件中有一个会立即返回假,因为在前面的循环中有一个子列表的元素会全部消耗光     while(leftPtr < left.size()){         merged.add(left.get(leftPtr));         leftPtr++;     }     while(rightPtr < right.size()){         merged.add(right.get(rightPtr));         rightPtr++;     }     return merged; } 

转载请标明出处:记录:列表排序(二)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!