当前位置:   article > 正文

排序算法——堆排序,快速排序_实现快速排序和堆排序

实现快速排序和堆排序

如有错误,欢迎指出,多谢。

动图来自菜鸟教程,多谢。

一:堆排序

堆排序相对来说有些难度,这里给个链接,老师讲的很详细,C语言版的:

https://www.bilibili.com/video/av47196993

 根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆,又称最大堆(大顶堆)

  1. 了解一下堆排序的大概流程:
  2. 1,我们给定一个数组,将数据依次放入堆节点中,它们的下标不变,上到下,左到右依次为0,1.....,
  3. 将父节点和子节点比较,最大的成为新的父节点,这个过程称之为heapify
  4. 2,我们使它在数据上也满足大顶堆的概念。从堆的倒数第二行向上遍历,比较每一个节点和它的的子节点,
  5. 使最大的变成新的父节点,我们发现,每完全执行一次,就会有一个最大数被换到堆顶,
  6. 这个过程称之为build_heap
  7. 3,我们将堆顶的最大数和堆的最后一个数交换,交换后,最大数位于堆的最底部,最右端,砍掉这个数不会影响堆的结构,
  8. 但我们就获得了最大数,这个就是heap_sort
  1. import random
  2. #该方法用于在父节点和子节点中找到最大值,将最大值变成父节点
  3. def heapify(arr,n,i):
  4. #递归出口
  5. # if i >= n:
  6. # return
  7. #左节点,右节点的下标
  8. left_index = 2*i+1
  9. right_index = 2*i+2
  10. #设父节点的下标为最大值的下标
  11. max_index = i
  12. #在下标未越界的条件下判断值是否大于父节点的值
  13. if left_index<n and arr[left_index]>arr[max_index]:
  14. max_index = left_index
  15. if right_index<n and arr[right_index]>arr[max_index]:
  16. max_index = right_index
  17. #如果max_index不等于i说明最大值不是父节点,交换
  18. if max_index != i:
  19. arr[max_index],arr[i] = arr[i],arr[max_index]
  20. #递归执行,自带出口
  21. heapify(arr,n,max_index)
  22. # print(max_index)
  23. #该方法用于建堆
  24. def build_heap(arr,n):
  25. #获取最后一个节点的下标
  26. last_index = n - 1
  27. #获取最后一个节点的父节点
  28. p_index = (last_index-1)//2
  29. #从最后一个父节点向前遍历节点,进行heapify
  30. i = p_index
  31. while i >= 0:
  32. heapify(arr,n,i)
  33. # print(arr)
  34. i = i - 1
  35. def heapsort(arr,n):
  36. build_heap(arr,n)
  37. i = n-1
  38. #从最后一个节点开始
  39. while i >= 0:
  40. #交换堆顶和堆尾的值,最大值在堆尾,堆的长度递减就不会再次比较堆尾的值
  41. # 即相当于去掉了堆尾
  42. arr[i],arr[0]=arr[0],arr[i]
  43. #交换完后继续进行heapify
  44. heapify(arr,i,0)
  45. i -= 1
  46. if __name__ == '__main__':
  47. arr = []
  48. x = random.randint(2,20)
  49. for i in range(0,x):
  50. arr.append(random.randint(1,1000))
  51. print("排序前:",arr)
  52. heapsort(arr,len(arr))
  53. # build_heap(arr,len(arr))
  54. # arr = [4,10,3,5,1,2]
  55. # heapify(arr,len(arr),0)
  56. print("排序后:",arr)

二:快速排序:

简单快排(即刻手写版)

缺点:需要额外申请空间

  1. import random
  2. def qsort_simple(arr):
  3. #递归出口
  4. if len(arr) < 2:
  5. return arr
  6. else:
  7. #取第一个为主元
  8. pivot_index = 0
  9. pivot = arr[pivot_index]
  10. #小于主元的放在左边,大于主元的放在右边,给两个数组
  11. left_arr = []
  12. right_arr = []
  13. for i in arr[pivot_index+1:]:
  14. if i > pivot:
  15. right_arr.append(i)
  16. else:
  17. left_arr.append(i)
  18. #调用递归,合并结果
  19. return qsort_simple(left_arr) + [pivot] + qsort_simple(right_arr)
  20. if __name__ == '__main__':
  21. arr = []
  22. x = random.randint(2,20)
  23. for i in range(0,x):
  24. arr.append(random.randint(1,1000))
  25. print("排序前:",arr)
  26. print("排序后:",qsort_simple(arr))

真正意义的快排:

一趟快速排序的算法是:

1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;

2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];

3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]的值交换;

4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换;

5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

  1. import random
  2. # #定义partition函数,参数数组,起始值,结尾值
  3. def partition(arr,beg,end):
  4. #主元下标取起始值
  5. pivot_index = beg
  6. pivot = arr[pivot_index]
  7. #获取指针,左指针为主元下标后一个,右指针最后一个
  8. left = pivot_index + 1
  9. right = end - 1
  10. while True:
  11. #当左指针小于等于右指针,且指针指向的数小于主元,指针右移
  12. while left <= right and arr[left] < pivot:
  13. left += 1
  14. #当右指针大于等于左指针,且指针指向的数大于等于主元,指针左移
  15. while right >= left and arr[right] >= pivot:
  16. right -= 1
  17. #退出条件,当左指针大于右指针,break
  18. if left > right:
  19. break
  20. #不满足条件且不满足退出时,交换值
  21. else:
  22. arr[left],arr[right] = arr[right],arr[left]
  23. #退出代表:此时的右指针在左指针的左侧,指向最小数,因此,需要将主元与right指向的数进行交换
  24. arr[pivot_index],arr[right] = arr[right],arr[pivot_index]
  25. #此时,主元的位置与right进行了交换,我们返回主元位置即返回right
  26. return right
  27. def qsort_partition(arr,beg,end):
  28. #递归出口
  29. if beg < end:
  30. #找到主元位置
  31. pivod = partition(arr,beg,end)
  32. #左右操作
  33. qsort_partition(arr,beg,pivod)
  34. qsort_partition(arr,pivod+1,end)
  35. if __name__ == '__main__':
  36. arr = []
  37. x = random.randint(2,20)
  38. for i in range(0,x):
  39. arr.append(random.randint(1,1000))
  40. print("排序前:",arr)
  41. qsort_partition(arr,0,len(arr))
  42. print("排序后:",arr)

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/725636
推荐阅读
相关标签
  

闽ICP备14008679号