1.简介
排序:将一组无序的记录序列按照某种逻辑顺序重新排序,调整为有序的记录序列的过程。
2.排序算法分类:
由于待排序的记录数量不同,使得排序过程中涉及的存储器不同,可将排序算法分为两大类:
对于具有多个相同值的记录序列来说,如果采用的排序算法使得排序前后拥有相同值记录的相对位置是否有改变可分为:
根据记录在存储介质上的组织方式划分排序算法的分类可分为:
3.常见排序算法
常见的排序算法主要有十种:冒泡排序算法、选择排序算法、插入排序算法、希尔排序算法、快速排序算法、堆排序算法、计数排序算法、桶排序算法、基数排序算法。
按照时间复杂度划分:
4.排序算法基本思路及实现
冒泡排序基本思想:通过相邻元素之间的比较与交换,使值较小的元素逐步从后面移到前面,值较大的元素从前面移到后面,就像水底的气泡一样向上冒,是稳定性排序算法。
def bubbleSort(self, arr):
for i in range(len(arr)):
for j in range(len(arr) - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
选择排序基本思想:每一趟排序中,从剩余未排序元素中选择一个最小的元素,与未排好序的元素最前面一个交换位置,是非稳定性排序算法。
def selectionSort(arr):
for i in range(len(arr) - 1):
min_pos = i
for j in range(i + 1, len(arr)):
if arr[min_pos] > min[j]:
min_pos = j
if i != min_pos:
arr[i], arr[min_pos] = arr[min_pos], arr[i]
return arr
插入排序基本思想:每一趟排序中,将剩余未排序元素中第一个元素,插入到排序元素中的合适位置上,是稳定性排序算法。
def insertionSort(arr):
for i in range(1, len(arr)):
temp = arr[i]
j = i
while j > 0 and arr[j - 1] > temp:
arr[j] = arr[j - 1]
j -= 1
arr[j] = temp
return arr
希尔排序基本思想:将整个序列按照一定间隔取值划分为若干个子序列,每个子序列使用插入排序,直到最后一轮排序间隔未1,对整个序列进行插入排序,为非稳定性排序算法。
def shellSort(arr):
size = len(arr)
gap = size // 2
while gap > 0:
for i in range(gap, size):
temp = arr[i]
j = i
while j >= gap and arr[j - gap] > temp:
arr[j] = arr[j - gap]
j -= gap
arr[j] = temp
gap = gap // 2
return arr
归并排序基本思想:采用经典的分治策略,先递归将当前序列分为两半,然后将有序序列合并成一个有序序列,是稳定性排序算法。
def merge(left_arr, right_arr):
arr = []
while left_arr and right_arr:
if left_arr[0] <= right_arr[0]:
arr.append(left_arr.pop(0))
else:
arr.append(right_arr.pop(0))
while left_arr:
arr.apend(left_arr.pop(0))
while right_arr:
arr.apend(right_arr.pop(0))
return arr
def mergeSort(arr):
size = len(arr)
if size < 2:
return arr
mid = len(arr) // 2
left_arr, right_arr = arr[0: mid], arr[mid:]
return merge(mergeSort(left_arr), mergeSort(right_arr))
快速排序基本思想:通过一趟排序将无序序列分为独立的两个序列,第一个序列的值均比第二个序列的值小。然后递归两个子序列,以达到整个序列有序,非稳定性排序算法。
def randomPartition(arr, low, high):
i = random.randint(low, high)
arr[i], arr[high] = arr[high], arr[i]
return partition(arr, low, high)
def partition(arr, low, high):
i = low - 1
pivot = arr[high]
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
def quickSort(arr, low, high):
if low < high:
pi = randomPartition(arr, low, high)
quickSort(arr, low, pi - 1)
quickSort(arr, pi + 1, high)
堆排序基本思想:借用堆结构设计的排序算法,将数组转化为大顶堆,重复从大顶堆中取出数值最大的节点,并让剩余的堆维持大顶堆性质,非稳定性排序。
def heapify(arr, index, end):
left = index * 2 + 1
right = left + 1
while left <= end:
max_index = index
if arr[left] > arr[max_index]:
max_index = left
if right <= end and arr[right] > arr[max_index]:
max_index = right
if index == max_index:
break
arr[index], arr[max_index] = arr[max_index], arr[index]
index = max_index
left = index * 2 + 1
right = left + 1
def buildMaxHeap(arr):
size = len(arr)
for i in range((size - 2) // 2, -1, -1):
heapify(arr, i, size - 1)
return arr
def maxHeapSort(arr):
buildMaxHeap(arr)
size = len(arr)
for i in range(size):
arr[0], arr[size - i - 1] = arr[size - i - 1], arr[0]
heapify(arr, 0, size - i - 2)
return arr
计数排序基本思想:使用额外的数组counts,其中counts[i]保存arr中值为i的个数,然后根据数组counts将arr中元素排到正确的位置,是稳定排序算法。
def countingSort(arr):
arr_min, arr_max = min(arr), max(arr)
size = arr_max - arr_min + 1
counts = [0 for _ in range(size)]
for num in arr:
counts[num - arr_min] += 1
for j in range(1, size):
counts[j] += counts[j - 1]
res = [0 for _ in range(len(arr))]
for i in range(len(arr) - 1, -1, -1):
res[counts[arr[i] - arr_min] - 1] = arr[i]
counts[arr[i] - arr_min] -= 1
return res
桶排序基本思想:将未排序的数组分成若干个桶(分成n个大小相同的区间),每个桶中的元素再进行单独排序(使用插入、归并、快排等),是稳定性排序算法。
def insertionSort(arr):
for i in range(1, len(arr)):
temp = arr[i]
j = i
while j > 0 and arr[j - 1] > temp:
arr[j] = arr[j - 1]
j -= 1
arr[j] = temp
return arr
def bucketSort(arr, bucket_size = 5):
arr_min, arr_max = min(arr), max(arr)
bucket_count = (arr_max - arr_min) // bucket_size + 1
buckets = [[] for _ in range(bucket_count)]
for num in arr:
buckets[(num - arr_min) // bucket_size].append(num)
res = []
for bucket in buckets:
insertionSort(bucket)
res.extend(bucket)
return res
基数排序基本思想:将整数按位数切割成不同的数字,然后按每个位数分别比较进行排序,是稳定性排序算法。
def radixSort(arr):
size = len(str(max(arr)))
for i in range(size):
buckets = [[] for _ in range(10)]
for num in arr:
buckets[num // (10 ** i) % 10].append(num)
arr.clear()
for bucket in buckets:
for num in bucket:
arr.append(num)
return arr
1.题目描述
题目链接
2.解析思路及代码
使用两个指针指向两个数组的逻辑长度尾部,再用一个指针指向第一个数组的真实长度尾部,然后把较大元素放到第一个数组的尾部,然后相应指针变化即可,最后如果第二个数组不为空则将第二个数组所有值存到第一个数组中。
public void merge(int[] nums1, int m, int[] nums2, int n) {
int index1 = m - 1, index2 = n - 1, index = m + n - 1;
while (index1 >= 0 && index2 >= 0) {
if (nums1[index1] <= nums2[index2]) {
nums1[index] = nums2[index2];
index2 --;
} else {
nums1[index] = nums1[index1];
index1 -- ;
}
index -- ;
}
while (index2 >= 0) {
nums1[index] = nums2[index2];
index -- ;
index2 -- ;
}
}
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
index = m + n - 1
m -= 1
n -= 1
while m >= 0 and n >= 0:
if nums1[m] <= nums2[n]:
nums1[index] = nums2[n]
n -= 1
else:
nums1[index] = nums1[m]
m -= 1
index -= 1
while n >= 0:
nums1[index] = nums2[n]
index -= 1
n -= 1
1.题目描述
题目链接
2.解题思路及代码
使用以上讲解的任意算法即可。
public int[] sortArray(int[] nums) {
Arrays.sort(nums);
return nums;
}
class Solution:
def randomized_partition(self, nums, l, r):
pivot = random.randint(l, r)
nums[pivot], nums[r] = nums[r], nums[pivot]
i = l - 1
for j in range(l, r):
if nums[j] < nums[r]:
i += 1
nums[j], nums[i] = nums[i], nums[j]
i += 1
nums[i], nums[r] = nums[r], nums[i]
return i
def randomized_quicksort(self, nums, l, r):
if r - l <= 0:
return
mid = self.randomized_partition(nums, l, r)
self.randomized_quicksort(nums, l, mid - 1)
self.randomized_quicksort(nums, mid + 1, r)
def sortArray(self, nums: List[int]) -> List[int]:
self.randomized_quicksort(nums, 0, len(nums) - 1)
return nums
1.题目描述
题目链接
2.解题思路及代码
public int[] sortedSquares(int[] nums) {
int l = 0, r = nums.length - 1;
int[] res = new int[nums.length];
int index = nums.length - 1;
while (l <= r) {
if (nums[l] * nums[l] >= nums[r] * nums[r]) {
res[index] = nums[l] * nums[l];
l ++ ;
} else {
res[index] = nums[r] * nums[r];
r -- ;
}
index -- ;
}
return res;
}
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
l, r = 0, len(nums) - 1
index = len(nums) - 1
res = [0] * len(nums)
while l <= r:
if nums[l] * nums[l] >= nums[r] * nums[r]:
res[index] = nums[l] * nums[l]
l += 1
else:
res[index] = nums[r] * nums[r]
r -= 1
index -= 1
return res
1.题目描述
题目链接
2.解题思路及代码
计数排序
class Solution {
public int[] relativeSortArray(int[] arr1, int[] arr2) {
int bounds = 0;
for (int x : arr1) {
bounds = Math.max(bounds, x);
}
int[] frequency = new int[bounds + 1];
for (int x : arr1) {
frequency[x] ++ ;
}
int[] ans = new int[arr1.length];
int index = 0;
for (int x : arr2) {
for (int i = 0; i < frequency[x]; i ++ ) {
ans[index ++ ] = x;
}
frequency[x] = 0;
}
for (int i = 0; i <= bounds; i ++ ) {
for (int j = 0; j < frequency[i]; j ++ ) {
ans[index ++ ] = i;
}
}
return ans;
}
}
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
bounds = max(arr1)
frequency = [0] * (bounds + 1)
for x in arr1:
frequency[x] += 1
ans = list()
for x in arr2:
ans.extend([x] * frequency[x])
frequency[x] = 0
for x in range(bounds + 1):
if frequency[x] > 0:
ans.extend([x] * frequency[x])
return ans
1.题目描述
题目链接
2.解题思路及代码
插入排序的思路,需要注意两点:
public ListNode insertionSortList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode dummyHead = new ListNode(0);
dummyHead.next = head;
ListNode lastSorted = head, cur = head.next;
while (cur != null) {
if (lastSorted.val <= cur.val) {
lastSorted = lastSorted.next;
} else {
ListNode pre = dummyHead;
while (pre.next.val <= cur.val) pre = pre.next;
lastSorted.next = cur.next;
cur.next = pre.next;
pre.next = cur;
}
cur = lastSorted.next;
}
return dummyHead.next;
}
}
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def insertionSortList(self, head: ListNode) -> ListNode:
if not head:
return head
dummyHead = ListNode(0, head);
lastSorted, cur = head, head.next
while cur:
if lastSorted.val <= cur.val:
lastSorted = lastSorted.next
else:
pre = dummyHead
while pre.next.val <= cur.val:
pre = pre.next
lastSorted.next = cur.next
cur.next = pre.next
pre.next = cur
cur = lastSorted.next
return dummyHead.next