(从小到大)
①直接插入
- (第一层循环)从第一个元素i开始
- (第二层循环)取出i的下一个数,向前遍历,如果比前一个数小,就换位
public static void sort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j > 0; j--) {
if (a[j] < a[j - 1]) {
int temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
}
}
}
②简单选择
- (第一层循环)i遍历
- (第二层循环)从未排序序列中(i之后),找到最小的元素min,如果最小元素不是未排序序列的第一个元素(i),则min和i互换
public static void sort(int[] a) {
for (int i = 0; i < a.length; i++) {
int min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) {
min = j;
}
}
if (min != i) {
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
}
③冒泡排序
- (第一层循环)取出每个数i准备比较,只需要比较n-1个数,每次可以固定在末尾一个最大的数
- (第二层循环)每次从第一个数起比较相邻的元素。如果第一个比第二个大,就交换他们两个。从开始第一对到结尾的最后一对,一共需要比较n-i-1次(i次就代表已经固定了最大i个元素)。这步做完后,最后的元素会是最大的数。
public static void sort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = 0; j < a.length - i - 1; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
④快速排序(双路)
- 从数列中挑出一个元素,称为"基准"(pivot)。
- 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
递归 地把小于基准值元素的子数列和大于基准值元素的子数列排序。
伪代码:
- i = L; j = R; 将基准数挖出形成第一个坑a[i]。
- j- -,由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。
- i++,由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。
- 再重复执行2,3二步,直到i==j,将基准数填入a[i]中
虽然 Worst Case 的时间复杂度达到了 O(n2),但是人家就是优秀,在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好。
public static void sort(int[] a, int low, int high) {
if (low >= high) {
return;
}
int left = low;
int right = high;
int pivot = a[left];
while (left < right) {
while (left < right && a[right] >= pivot)
right--;
a[left] = a[right];
while (left < right && a[left] <= pivot)
left++;
a[right] = a[left];
}
a[left] = pivot;
sort(a, low, left - 1);
sort(a, left + 1, high);
}
单路、双路、三路快排
⑤归并排序
def sort(lst, low, mid, high):
i = low
j = mid +1
lstm = []
while i <= mid and j <= high:
if lst[i] < lst[j]:
lstm.append(lst[i])
i += 1
else:
lstm.append(lst[j])
j += 1
while i <= mid:
lstm.append(lst[i])
i += 1
while j <= high:
lstm.append(lst[j])
j += high
lst[low: high+1] = lstm
def merge_sort(lst, low, high):
if low < high:
mid = (low + high) // 2
merge_sort(lst, low, mid)
merge_sort(lst, mid + 1, high)
sort(lst, low, mid, high)
list=[5,4,5,6,6,5,4,4,1,1,22,3,2]
n=len(list)
merge_sort(list,0,n-1)
print(list)
⑥堆排序
大根堆:每个结点的值都大于或等于左右孩子结点 小根堆:每个结点的值都小于或等于左右孩子结点
步骤:
- 首先将待排序的数组构造出一个
大根堆 - 取出这个大根堆的堆顶节点(最大值),与堆的最下最右的元素(即最小值)进行交换,然后把剩下的元素再构造出一个大根堆
(此时最大值在数组末尾,以后建堆不再用它了) - 重复第二步,直到这个大根堆里的数被取完,此时被取出的数完成
从小到大 排序。
构建大根堆:
- 构造堆排序从
end // 2 - 1 开始倒序,意思是找到每个有子节点的节点,调整每个小树,使它符合大顶堆 - 构建大根堆就是每个子树的根节点和较大的子节点进行值交换
def heap_sort(alist):
def siftdown(alist,begin, end):
e=alist[begin]
i, j = begin, begin * 2 + 1
while j < end:
if j + 1 < end and alist[j] < alist[j + 1]:
j += 1
if e > alist[j]:
break
alist[i] = alist[j]
i, j = j, j * 2+1
alist[i] = e
end = len(alist)
for i in range(end // 2 - 1, -1, -1):
siftdown(alist, i, end)
for i in range((end - 1), 0, -1):
alist[i],alist[0] = alist[0],alist[i]
siftdown(alist, 0, i)
return alist
if __name__ == "__main__":
alist = [4,10,3,5,1]
print(alist)
heap_sort(alist)
print(alist)
|