对于直接插入排序、折半插入排序、选择排序、冒泡排序、归并排序,快速排序、堆排序算法的Python实现进行记录。
注:所有LeetCode系列文章均是为了复习作为记录,思维可能有跳跃,有疑问欢迎一起讨论。
将列表分为有序表 nums[ : i] 与无序表 nums[i : ] 两部分,通过“比较” +“移动” 两步操作将 nums[i] 放到有序表对应部分,向后迭代 i 至列表尾部,完成排序。
for i in range(len(nums_1)):
for j in range(i):
if (nums_1[i] < nums_1[j]):
temp = nums_1[i];
nums_1[j + 1: i + 1] = nums_1[j: i];
nums_1[j] = temp;
print(nums_1)
直接插入排序中的 “比较” 实际上为找出 nums[i] 在有序表中的位置,可以将顺序查找优化为折半查找,注意最终查找的位置与 low 和 high 的关系。
for i in range(len(nums_2)):
low = 0;
high = i - 1;
while (low <= high):
mid = low + (high - low) // 2;
if (nums_2[mid] >= nums_2[i]):
high = mid - 1;
else:
low = low + 1;
temp = nums_2[i];
nums_2[low + 1 : i + 1] = nums_2[low : i];
nums_2[low] = temp;
print(nums_2)
依次选出列表中最小的数,插入表前。
for i in range(len(nums_3)):
j = i;
temp_index = j;
temp = nums_3[j];
while (j < len(nums_3)):
if (nums_3[j] < temp):
temp_index = j;
temp = nums_3[j];
j = j + 1;
nums_3[temp_index] = nums_3[i];
nums_3[i] = temp;
print(nums_3)
依次交换,大数向后移动,每轮确定一个数的最终位置,当该轮未发生交换时,可提前结束(用tag记录);
for i in range(len(nums_4)):
tag = 0;
for j in range(len(nums_4) - i - 1):
if (nums_4[j] > nums_4[j + 1]):
tag = 1;
nums_4[j], nums_4[j + 1] = nums_4[j + 1], nums_4[j];
if (tag == 0):
break
print (nums_4)
二路归并,左半部分数组排序,右半部分数组排序,最后合并。
def merge(left, right):
"""
:param left: 有序数组;
:param right: 有序数组;
:return: 返回合并后的有序数组。
"""
mat = [];
i, j = 0, 0;
len_left = len(left);
len_right = len(right);
while ((i < len_left) & (j < len_right)):
if (left[i] < right[j]):
mat.append(left[i]);
i += 1;
else:
mat.append(right[j]);
j += 1;
mat.extend(left[i : ]);
mat.extend(right[j : ]);
return mat
def merge_sort(nums_5):
if len(nums_5) <= 1:
return nums_5;
mid = len(nums_5) // 2;
left = merge_sort(nums_5[ : mid]);
right = merge_sort(nums_5[mid : ]);
return merge(left, right);
每轮选出一个 pivot ,使其左边的小于 pivot ,右边大于 pivot 。每轮比较过后,pivot 与 right_idx 的值进行互换。
def quick_sort(array, start_idx, end_idx):
if ((end_idx - start_idx) < 1):
return
pivot_idx = start_idx;
left_idx = start_idx + 1;
right_idx = end_idx;
while (left_idx <= right_idx):
if ((array[left_idx] > array[pivot_idx]) & (array[right_idx] < array[pivot_idx])):
array[left_idx], array[right_idx] = array[right_idx], array[left_idx];
if (array[left_idx] < array[pivot_idx]):
left_idx += 1;
if (array[right_idx] > array[pivot_idx]):
right_idx -= 1;
array[right_idx], array[pivot_idx] = array[pivot_idx], array[right_idx];
quick_sort(array, start_idx, right_idx - 1); # 这里不能用切片,需要对原数组进行修改。
quick_sort(array, left_idx, end_idx);
数组与树联系的关键在于, 堆排序主要分为两步操作:建堆 + 弹出。
def Sort(array):
for i in range(1, len(array)):
father = int((i - 1) / 2);
while ((i != 0) and (array[father] > array[i])): # 逻辑运算符要加括号。
array[father], array[i] = array[i], array[father];
i = father;
father = int((i - 1) / 2);
return array;
def heap_sort(array):
mat = [];
while(len(array) != 0):
Sort(array);
mat.append(array[0]);
array = array[1 : ];
return mat;
print(heap_sort(nums_7))
简单选择排序、希尔排序、快速排序、堆排序为不稳定算法;快速排序、堆排序、归并排序时间复杂度为:O(nlogn)。