手撕排序算法(java实现)

本文总结了频繁出现在面试题中的排序算法,并提供了java和python两种语言实现,作为自己复习的总结,也希望对其他找工作的朋友们有所帮助。

一、快速排序:

      快速排序通常情况下,是用于排序的最佳的实用选择。这是因为其平均性能相当好:期望的运行时间为O(nlogn),且O(nlogn)记号中隐藏的常数因子很小。另外,它还能够进行就地排序,在虚存环境中也能很好地工作。接下来我们便来好好了解一下快速排序的思想。

1、时间复杂度: best: O(n*logn)      average: O(n*logn)      worst: O(n^2)

2、空间复杂度: O(logn)

3、算法描述:

像合并排序一样,快速排序也是基于分支模式的,主要分为以下三个步骤:分解、解决、合并

4、快速排序的数据结构:

QUICKSORT(A, p, r)
    if p<r
        then q <- PARTITION(A, p, r)
            QUICKSORT(A, p, q-1)
            QUICKSORT(A, q+1, r)

为排序一个完整的数组A,最初的调用是QUICKSORT(A, 1, length(A))

快速排序算法的关键是PARTITION过程,它对子数组A[p...r]进行就地重排:

PARTITION(A,p, r)
    x <- A[r]
    i <- p-1
    for j <- p to r-1
        do if A[j]<=x
            then i <- i+1
                exchange A[i] <-> A[j]
    exchange A[i+1] <-> A[r]
    return i+1

5、python实现快速排序代码:

'''
    quick_sort
    author: fuhongyu
    time: 2018-07-27
    time complecity: O(nlog(n))
    object:15 minutes
'''

def quick_sort(array, l, r):
    if l < r:
        q = partition(array, l, r)
        quick_sort(array, l, q - 1)
        quick_sort(array, q + 1, r)
    return array
 
def partition(array, l, r):
    x = array[r]
    i = l - 1
    for j in range(l, r):
        if array[j] <= x:
            i += 1
            array[i], array[j] = array[j], array[i]
    array[i + 1], array[r] = array[r], array[i+1]
    return i + 1

测试快速排序代码:

lists = [3,5,1,2,7]
quick_sort(lists, 0, len(lists)-1)

 6、java实现快速排序:

package test;

/**
 * 
 * @author FHY
 * 实现快速排序
 * 2019.6.6
 */
public class QuickSortDemo {
	public static void main(String[] args) {
		int[] nums = {2,4,1,6,3,8,5};
		int n = nums.length;
		quickSort(nums, 0, n-1);
		for (int i : nums) {
			System.out.println(i);
		}	
	}

	private static void quickSort(int[] nums, int p, int n) {
			if (p>=n) return;
			int q = getPartition(nums,p, n);//获取分区
			quickSort(nums, p, q-1);
			quickSort(nums, q+1, n);		
	}		
	
	/** 
	 * @param nums 数组
	 * @param p 要比较的左边界
	 * @param r 要比较的右边界
	 * @return 返回划分分区的中间节点
	 * 将最后一个元素作为标志位pivot,通过比较将小于标志位的元素放到左边,大于标志位的放到右边
	 */
	private static int getPartition(int[] nums, int p, int r) {
		int pivot = nums[r]; //把最后一个元素作为标志
		int i = p; 
		
		for(int j = p; j <= r-1; j++){
			if(nums[j] < pivot){
				//交换nums[j]和nums[i]
				int temp = nums[i];
				nums[i] = nums[j];
				nums[j] = temp;
				i++;
			}
		}
		//交换pivot和nums[i]
		int temp1 = nums[i];
		nums[i] = nums[r];
		nums[r] = temp1;
		return i;
	}
}

二、归并排序:

1、简单介绍:归并排序采取了分治法的思想,在每一层递归上都有三个步骤:<1>分解 <2>解决 <3> 合并

2、时间复杂度:best: O(n*logn)      average: O(n*logn)      worst: O(n*logn)

3、空间复杂度:O(n)

4、合并排序算法数据结构:

MERGE_SORT(A, p, r)
    if p < r
        then q <- (p+r)/2  # 取下限
           MERGE_SORT(A, p, q) 
           MERGE_SORT(A, q+1, r)
           MERGE(A, p, q, r)

5、python实现合并排序算法代码:

'''
    merge_sort
    author: fuhongyu
    time: 2018-07-27
    time complexity: O(n^2)
    objective:15 minutes
    
''' 
def merge(a ,b):#  合并两个list
    i = 0
    j = 0
    result = []
    while i<len(a) and j <len(b):
        if a[i] < b[j]:
            result.append(a[i])
            i += 1
        else:
            result.append(b[j])
            j += 1
    if i == len(a):
        for i in b[j:]:
            result.append(i)
    else:
        for i in a[i:]:
            result.append(i)
    return result


def merge_sort(lists): 
    if len(lists) <= 1:
        return lists
    middle = len(lists)//2
    left = merge_sort(lists[:middle])
    right = merge_sort(lists[middle:])
    return merge(left, right)

测试排序函数:

lists = [3,4,2,6,4,8,3,0,20,34,1,4,56,3]
merge_sort(lists)

6、java代码实现:

package test;

/**
 * @author FHY
 * 归并排序算法实现
 * 2019.6.6
 */
public class MergeSortMain {

	public static void main(String[] args) {
		int[] nums = {2,4,1,6,3,8,5};
		int n = nums.length - 1;
		merge(nums, 0, n);
		for (int i : nums) {
			System.out.println(i);
		}
	}
	
	public static void merge(int[] arr, int start, int end){
		if (start >= end) 
			return;
		int mid = start + (end - start)/2;
		merge(arr, start, mid);
		merge(arr, mid + 1, end);
		sort(arr, start, mid, end);
	}

	private static void sort(int[] arr, int start, int mid, int end) {
		int index1 = start;
		int index2 = mid + 1;
		int[] result = new int[end - start + 1];
		int index = 0;
		while(index1 <= mid && index2 <= end){
			if(arr[index1] <= arr[index2]){
				result[index++] = arr[index1++];
			}else
				result[index++] = arr[index2++];
		}
		if(index1 <= mid)
			result[index++] = arr[index1++];
		else if(index2 <= end)
			result[index++] = arr[index2++];
		for(int i = 0; i < result.length; i++){
			arr[start+i] = result[i];
		}
	}
}

补充:归并算法,归即递归,并即合并。该算法运行速度很快,但因为是递归算法,故对CPU消耗很大

 

三、插入排序:

1、简单介绍:插入排序作为最基本的入门排序,算法思想最简单,最容易实现。

该算法是一个就地排序算法,思想是:将数组A中的元素A[1......n]依此插入到已经拍好序的sequenceA中。

2、时间复杂度: best: O(n)      average: O(n^2)     worst: O(n^2)

3、空间复杂度: O(1)

4、插入排序的数据结构

INSERTION-SORT(A)
    for j <- 2 to length[A]
    do key <- A[j]
        # Insert A[j] into the sorted sequence A[1...j-1].
        i <- j-1
        while i>0 and A[i]>key
            do A[i+1] <- A[i]
                i <- i-1
        A[i+1] <- key

4、python实现插入排序代码:

'''
    insert_sort
    author: fuhongyu
    time: 2018-07-27
    time compliexity:O(n^2)
    objective: 10 minutes
'''
def inser_sort(lists):
    for i in range(1,len(lists)):
        key = lists[i]
        j = i-1
        # insert lists[j] into sequence lists
        while j >= 0:
            if lists[j] > key:
                lists[j+1] = lists[j]
                lists[j] = key
            j -= 1
    return lists

5、java代码实现:待补。。。。。。

 

四、堆排序:

1、简单介绍:像合并排序而不像插入排序,堆排序的运行时间是O(n*logn)。像插入排序而不像合并排序,他是一种原地排序算法,在任何时候,数组中只有常数个元素存储在输入数组以外。这样,堆排序就把上述两种排序的算法的优点结合起来了。

2、时间复杂度: best: O(n*logn)      average: O(n*logn)      worst: O(n*logn)

3、空间复杂度:O(1)

4、算法说明:堆排序过程主要分为三步:

      1)保持堆的性质:将堆调整为最大堆:MAX-HEAPIFY(A, i),使i为根的子树称为最大堆。

      2)建堆: BUILD-MAX-HEAPIFY :将一个数组A[1...n]变成一个最大堆。

      3)堆排序算法:HEAPSORT(A) :  将数组A进行排序

5、python实现代码如下:

'''
    function:heap sort 
    author: fuhongyu
    time: 2018-07-28
    completion:15 minutes
    time complecity:O(n*logn)
'''
def max_heap(lists, i, size):
    lchild = 2*i 
    rchild = 2*i+1
    max = i
    if lchild < size and lists[lchild] > lists[max]:
        max = lchild
    if rchild < size and lists[rchild] > lists[max]:
        max = rchild
    if max != i:
        lists[i] , lists[max] = lists[max], lists[i]
        max_heap(lists, max, size)

def build_heap( lists):
    size = len(lists)
    for i in range(0, size//2)[::-1]:
        max_heap(lists, i, size)
    return lists

def heap_sort( lists):
    size = len(lists)
    lists = build_heap(lists)
    print(lists)
    for i in range(0, size)[::-1]:
        lists[i], lists[0] = lists[0], lists[i]
        max_heap(lists, 0 ,i)
    print(lists)

测试上面的程序:

lists = [4,1,3,2,16,9,10,14,8,7]
heap_sort(lists)

6、java代码实现:待补。。。。。。

7、应用:

       虽然堆排序算法是一个很漂亮的算法,但在实际中,快速排序的一个好的实现往往优于堆排序。尽管这样,堆数据结构还是有很大的用处。一个很常见的应用就是:作为高效的优先级队列,包括最大优先级队列和最小优先级队列,分别对应最大堆和最小堆。

一个堆可以在O(lgn)时间内,支持大小为n的集合上的任意优先队列的操作。

 

五、冒泡排序:

1、简单说明:冒泡排序的实现非常简单,时间复杂度大,但是作为经典的排序算法还是值得一提的。

2、python 实现冒泡排序算法代码:

'''  
     bubbling_sort
     author: fuhongyu
     time: 2018年7月27日
     时间复杂度: n^2
     目标:5 minutes

'''
def bubblesort(lists):
    for i in range(len(lists)-1):
        for j in range(i+1 , len(lists)):
            if lists[i] > lists[j]:
                temp = lists[i]
                lists[i] = lists[j]
                lists[j] = temp
    return lists

3、java代码实现:待补。。。。。。

总结:

排序算法时间复杂度和空间复杂度比较 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章