Java - Sorting Algorithms

本文深入探讨了三种主流排序算法:快速排序、归并排序和堆排序。详细介绍了它们的时间复杂度、空间复杂度,并提供了Java实现代码。快速排序通过递归分区进行排序;归并排序采用分治策略,将数组分为子数组进行排序后再合并;堆排序则基于二叉堆数据结构,通过构建最大堆并逐步移除最大元素来完成排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Complexity

QuicksortMergesortHeapsort
Time Complexity O(nlogn)O(nlogn)O(nlogn)
Space Complexity O(1)O(n)Could be O(1)

Quicksort

Quicksort is similar to MergeSort in that the sort is accomplished by dividing the array into two partitions and then sorting each partition recursively.

In Quicksort, the array is partitioned by placing all items smaller than some pivot item before that item and all items larger than the pivot item after it.

There are many different versions of Quicksort that pick pivot in different ways.

  1. Always pick first element as pivot.

  2. Always pick last element as pivot.

  3. Pick a random element as pivot.

  4. Pick median as pivot.

  • Implement Quicksort in Java using Arrays (Takes the last element as pivot)

public class QuickSortArray {
    
    private int partition (int arr[], int low, int high) {
        
        int pivot = arr[high];
        int i = low - 1;
        for (int j=low; j<high; j++) {
            // If current element is smaller than or equal to pivot
            if (arr[j] < pivot) {
                i++;
                //swap arr[i] and arr[j]
                int temp1 = arr[i];
                arr[i] = arr[j];
                arr[j] = temp1;
            }
        }
        
        //swap arr[i+1] and arr[high] (pivot)
        int temp2 = arr[i+1];
        arr[i+1] = arr[high];
        arr[high] = temp2;
        
        return i+1; //the position of pivot
    }
    
    public void quickSort (int[] arr, int low, int high) {
        
        if (low < high) {
            //pi is partitioning index
            int pi = partition (arr, low, high);
            
            // recursively sort elements before partition and after partition
            quickSort (arr, low, pi-1);
            quickSort (arr, pi+1, high);
        }
    }
}
  • Implement Quicksort in Java using LinkedList (Takes the median as pivot)

public class QuickSortList {

    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode mid = findMedian(head); // O(n)
        
        ListNode leftDummy = new ListNode(0), leftTail = leftDummy;
        ListNode rightDummy = new ListNode(0), rightTail = rightDummy;
        ListNode middleDummy = new ListNode(0), middleTail = middleDummy;
        while (head != null) {
            if (head.val < mid.val) {
                leftTail.next = head;
                leftTail = head;
            } else if (head.val > mid.val) {
                rightTail.next = head;
                rightTail = head;
            } else {
                middleTail.next = head;
                middleTail = head;
            }
            head = head.next;
        }
        
        leftTail.next = null;
        middleTail.next = null;
        rightTail.next = null;
        
        ListNode left = sortList(leftDummy.next);
        ListNode right = sortList(rightDummy.next);
        
        return concat(left, middleDummy.next, right);
    }
    
    private ListNode findMedian(ListNode head) {
        ListNode slow = head, fast = head.next;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    
    private ListNode concat(ListNode left, ListNode middle, ListNode right) {
        ListNode dummy = new ListNode(0), tail = dummy;
        
        tail.next = left; tail = getTail(tail);
        tail.next = middle; tail = getTail(tail);
        tail.next = right; tail = getTail(tail);
        return dummy.next;
    }
    
    private ListNode getTail(ListNode head) {
        if (head == null) {
           return null;
        } 
       
        while (head.next != null) {
            head = head.next;
        }
        return head;
    }
}

Mergesort

Mergesort is based on divide-and-conquer paradigm. It involves the following three steps:

  1. Divide the array into two (or more) subarrays.

  2. Sort each subarray (Conquer).

  3. Merge them into one.

  • Implement Mergesort in Java using Arrays

public class MergeSortArray {

    public void sortArray (int[] arr, int left, int right) {
        
        if (left < right) {
            int mid = left + (right - left)/2;
            sortArray (arr, left, mid);
            sortArray (arr, mid+1, right);
            mergeArray (arr, left, mid, right);
        }
    }
    
    private void mergeArray (int[] arr, int left, int mid, int right) {
        
        int n1 = mid - left + 1;
        int n2 = right - mid;
        
        int[] L = new int[n1];
        int[] R = new int[n2];
        
        for (int i=0; i < n1; i++) {
            L[i] = arr[left + i];        
        }
        for (int j=0; j < n2; j++) {
            R[j] = arr[mid + 1 + j];
        }
        
        /* Merge the temp arrays */         
        // Initial indexes of first and second subarrays
        int i = 0, j = 0;
 
        // Initial index of merged subarry array
        int k = left;
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]){
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }
 
        /* Copy remaining elements of L[] if any */
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }
 
        /* Copy remaining elements of R[] if any */
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }
}
  • Implement Mergesort in Java using LinkedList

/**
 * Definition for ListNode.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int val) {
 *         this.val = val;
 *         this.next = null;
 *     }
 * }
 */ 

public class MergeSortList {
    /**
     * @param head: The head of linked list.
     * @return: The head of the sorted linked list.
     */
    public ListNode sortList(ListNode head) {  
        
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode mid = findMid(head);
        ListNode right = sortList(mid.next);
        mid.next = null;
        ListNode left = sortList(head);
        
        return mergeList(left, right);
    }
    
    private ListNode findMid (ListNode head) {
        ListNode slow = head;
        ListNode fast = head.next;
            
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
        
    private ListNode mergeList (ListNode left, ListNode right) {
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
            
        while (left != null && right != null) {
            if (left.val <= right.val) {
               tail.next = left;
               left = left.next;
            } else {
                tail.next = right;
                right = right.next;
            }
            tail = tail.next;
        }    
        
        if (left != null) {
            tail.next = left;
        } else {
            tail.next = right;
        }
            
        return dummy.next;
    }
}

Heapsort

Heap sort is a comparison based sorting technique based on Binary Heap data structure. It is similar to selection sort where we first find the maximum element and place the maximum element at the end. We repeat the same process for remaining element.

Heap Sort Algorithm for sorting in increasing order:

  1. Build a max heap from the input data.

  2. At this point, the largest item is stored at the root of the heap. Replace it with the last item of the heap followed by reducing the size of heap by 1. Finally, heapify the root of tree.

  3. Repeat above steps while size of heap is greater than 1.

  • Implement Heapsort in Java using Arrays

public class HeapSort {
    
    public void sort(int arr[]) {
    
        int n = arr.length;
 
        // Build heap (rearrange array)
        for (int i = n / 2 - 1; i >= 0; i--)
            heapify(arr, n, i);
 
        // One by one extract an element from heap
        for (int i=n-1; i>=0; i--) {
            // Move current root to end
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
 
            // call max heapify on the reduced heap
            heapify(arr, i, 0);
        }
    }
 
    // To heapify a subtree rooted with node i which is
    // an index in arr[]. n is size of heap
    void heapify(int arr[], int n, int i) {
        int largest = i;  // Initialize largest as root
        int l = 2*i + 1;  // left = 2*i + 1
        int r = 2*i + 2;  // right = 2*i + 2
 
        // If left child is larger than root
        if (l < n && arr[l] > arr[largest])
            largest = l;
 
        // If right child is larger than largest so far
        if (r < n && arr[r] > arr[largest])
            largest = r;
 
        // If largest is not root
        if (largest != i) {
            int swap = arr[i];
            arr[i] = arr[largest];
            arr[largest] = swap;
 
            // Recursively heapify the affected sub-tree
            heapify(arr, n, largest);
        }
    }
}

References

  1. Foundations of Algorithms, Richard E. Neapolitan, Chapter 2 Divide and Conquer

  2. Sorting, CMU

  3. Big-O Algorithm Complexity Cheat Sheet

  4. Java sorting algorithms - Implementations

  5. Merge Sort, GeeksforGeeks

  6. Quick Sort, GeeksforGeeks

  7. Heap Sort, GeeksforGeeks

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值