python写希尔、堆、快速、归并排序

本文深入探讨了四种经典的排序算法:希尔排序、堆排序、快速排序和归并排序。从算法原理、实现细节、优缺点等方面进行了详细阐述,并通过实例代码展示了如何实现这些算法。

1 希尔排序:

def shell_sort(seq):
	gap = len(seq)/2 # 以gap为间隙,将数组分成gap组,0 到gap-1分属不同的组
	#pdb.set_trace()
	while gap > 0: # gap最小为1
		for i in range(0, gap): # 0 到 gap-1组,分别用直接插入排序处理每组,取得每组的第一个元素i
			for j in range(i+gap, len(seq), gap): # 确定这一组的若干元素,从第二个元素开始取待插入元素
				for k in range(i, j, gap): # 待插入元素与前面元素做对比,从第一个元素比起
					if seq[j] < seq[k]:
						tmp = seq[j]
						seq.pop(j)
						seq.insert(k, tmp)
		gap /=2

2 堆排序:

def heap_adjust(seq, end, mid):  # 建立大顶堆,end是尾元素下标,mid为中间位置元素
	#pdb.set_trace()
	for i in range(mid, -1, -1):# 堆,或者二叉树顺序存储结构的特性有:第i个元素的左右子节点为i*2+1和i*2+2,从中间位置元素开始往前,分别进行置换
		if i*2+1 > end: # 没有子节点
			continue
		if i*2+1 == end: # 有左子结点
			if seq[i] < seq[i*2+1]:
				seq[i], seq[i*2+1] = seq[i*2+1], seq[i]
		else:	# 有左右子节点,找到最小的赋予i位置
			if seq[i*2+1] < seq[i*2+2]:
				seq[i*2+1],seq[i*2+2] = seq[i*2+2],seq[i*2+1]
			if seq[i] < seq[i*2+1]:
				seq[i],seq[i*2+1] = seq[i*2+1], seq[i]

def heap_sort(seq):	# n个元素的大顶堆建立后,堆的首尾元素互换,n-1个元素重新建立大顶堆
	for i in range(len(seq)-1, 0, -1):
		mid = i/2
		heap_adjust(seq, i, mid)
		seq[0],seq[i] = seq[i], seq[0]

3 快速排序:

def median(seq, start, center, end): #put median number at start,将中值放在start位置,避免快排最坏情况出现
	if seq[start] > seq[end]:
		seq[start], seq[end] = seq[end], seq[start]
	if seq[start] > seq[center]:
		seq[start], seq[center] = seq[center], seq[start]
	if seq[center] > seq[end]:
		seq[start], seq[end] = seq[end], seq[start]
	else:
		seq[start], seq[center] = seq[center], seq[start]

def quik_sort(seq, start, end):
	if start >= end:				#终止条件
		return

	mid = (start + end)/2	
	median(seq, start, mid, end)	# 设定中值
	key = seq[start]
	lp = start # 左侧游标
	rp = end   # 右侧游标

	while True: # 进行一轮移动,移动结果为将start位置的中值移动到某位,其左侧都小于中值,右侧都大于中值
		while key < seq[rp] and rp > lp: # 从右侧游标开始比较并移动rp
			rp = rp - 1
		if rp > lp:
			seq[lp] = seq[rp] # 将右侧游标数据放到左侧游标位置
			lp = lp + 1 # 左侧游标前移,指向下一个待比较数据
		while key > seq[lp] and lp < rp: # 从左侧游标开始比较并移动lp
			lp = lp +1 
		if lp < rp:
			seq[rp] = seq[lp] # 将左侧游标数据放到右侧游标位置
			rp = rp -1 # 右侧游标前移,指向下一个待比较数据
		if lp >= rp: # 如果lp和rp会和,则终止循环
			break

	seq[lp] = key # 此时的lp指向中值应该放置的位置
	quik_sort(seq, start, rp-1)				# 分成两段进行分治
	quik_sort(seq, rp+1, end)

4. 归并排序

def merge_array(seq, start, mid, end):
	#pdb.set_trace()
	part_1 = seq[start:mid+1]
	part_2 = seq[mid+1:end+1]
	i = 0
	j = 0
	k = start
	while (i < len(part_1)) and (j < len(part_2)): 
		if part_1[i] < part_2[j]:
			seq[k] = part_1[i]
			i += 1
			k += 1
		else:
			seq[k] = part_2[j]
			j += 1
			k += 1

	for index in range(i, len(part_1)):
		seq[k] = part_1[index]
		k += 1

	for index in range(j, len(part_2)):
		seq[k] = part_2[index]
		k += 1

def merge_sort(seq, start, end):
	if end == start:
		return
	mid = (start + end)/2
	merge_sort(seq, start, mid)
	merge_sort(seq, mid+1, end)
	merge_array(seq, start, mid, end)


### Python 实现希尔排序、排序归并排序 #### 希尔排序流程图与代码实现 希尔排序是一种基于插入排序的改进版本,通过比较相隔一定间隔的元素来减少数据移动次数。随着间隔逐渐减小至1,最终使整个序列变得有序。 ```mermaid graph TD; A[开始] --> B(初始化增量gap=len/2); B --> C{gap>0?}; C -- 是 --> D(按增量分组进行直接插入排序); D --> E(gap=gap//2); E --> C; C -- 否 --> F[结束]; ``` ```python def shell_sort(arr): n = len(arr) gap = n // 2 while gap > 0: for i in range(gap, n): temp = arr[i] j = i while j >= gap and arr[j - gap] > temp: arr[j] = arr[j - gap] j -= gap arr[j] = temp gap //= 2 ``` #### 排序流程图与代码实现 排序利用了最大的数据结构特性,在构建完成后不断移除根节点的最大值并与最后一个叶子结点互换位置,从而逐步形成一个升序排列的结果列表。 ```mermaid graph TD; A[开始] --> B(建初始大顶); B --> C{未处理完毕?}; C -- 是 --> D(取顶记录作为当前子数组中最大的记录); D --> E(将该记录与尚未排序部分最末尾的一个记录交换位置); E --> F(调整剩余n-i个记录构成的新); F --> C; C -- 否 --> G[结束]; ``` ```python def heapify(arr, n, i): largest = i l = 2 * i + 1 r = 2 * i + 2 if l < n and arr[largest] < arr[l]: largest = l if r < n and arr[largest] < arr[r]: largest = r if largest != i: arr[i], arr[largest] = arr[largest], arr[i] heapify(arr, n, largest) def heap_sort(arr): n = len(arr) for i in range(n // 2 - 1, -1, -1): heapify(arr, n, i) for i in range(n-1, 0, -1): arr[i], arr[0] = arr[0], arr[i] heapify(arr, i, 0) ``` #### 归并排序流程图与代码实现 归并排序采用的是典型的分治法策略,即将原始数组分割成更小子集直到不能再分解为止;接着再逐一合并这些已排序好的片段,直至恢复原状却已是完全有序的状态。 ```mermaid graph TD; A[开始] --> B(判断是否只剩下一个元素或为空); B --> C{长度<=1?}; C -- 是 --> H(返回单个元素或空列表); C -- 否 --> D(找到中间索引mid=length//2); D --> E(左半边=merge_sort(前半部)); E --> F(右半边=merge_sort(后半部)); F --> G(合并两个有序数组得到新结果); G --> I[结束]; ``` ```python def merge(left, right): result = [] i = j = 0 while i < len(left) and j < len(right): if left[i] <= right[j]: result.append(left[i]) i += 1 else: result.append(right[j]) j += 1 result.extend(left[i:]) result.extend(right[j:]) return result def merge_sort(arr): if len(arr) <= 1: return arr mid = len(arr) // 2 left_half = merge_sort(arr[:mid]) # 对左边一半继续递归调用 right_half = merge_sort(arr[mid:]) # 对右边一半继续递归调用 return merge(left_half, right_half) # 将两部分合并起来 ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值