排序查询算法(一)
冒泡排序
# coding:utf-8
def bubble_sort(alist):
"""冒泡排序"""
nums = len(alist) - 1 # 要执行的次数
while nums:
for i in range(nums):
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
nums -= 1
return alist
if __name__ == "__main__":
b = bubble_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
print(b)
另一种方法
# coding:utf-8
def bubble_sort(alist):
"""冒泡排序"""
nums = len(alist)
count = 0 # 记录是否有进行数据交换
for j in range(nums-1): # 规定要执行的次数
for i in range(0, nums-1-j): # 规定每次执行比较的个数
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
count += 1
if count == 0: # 说明该序列是有序的序列,不必进行后面的比较,直接返回
return alist
return alist
if __name__ == "__main__":
b = bubble_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
print(b)
时间复杂度
- 最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
- 最坏时间复杂度:O(n2)
- 稳定性:稳定
改进:当传进来的顺序表是有序的时候
# coding:utf-8
def bubble_sort(alist):
"""冒泡排序"""
nums = len(alist)
count = 0 # 记录是否有进行数据交换
for j in range(nums-1): # 规定要执行的次数
for i in range(0, nums-1-j): # 规定每次执行比较的个数
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
count += 1
if count == 0: # 说明该序列是有序的序列,不必进行后面的比较,直接返回
return alist
return alist
if __name__ == "__main__":
b = bubble_sort([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(b)
选择排序
# coding:utf-8
def select_sort(alist):
"""选择排序"""
n = len(alist)
for j in range(n-1): # 外层循环代表执行多少次
min_index = j # j: 0 ~ n-2 共n-1个数字
for i in range(j, n): # 内层循环表示每次从哪开始
if alist[min_index] > alist[i]:
min_index = i
alist[j], alist[min_index] = alist[min_index], alist[j]
return alist
if __name__ == "__main__":
s = select_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
print(s)
时间复杂度
- 最优时间复杂度:O(n2)
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定(考虑升序每次选择最大的情况)
插入排序
# coding:utf-8
def insert_sort(alist):
"""插入排序"""
n = len(alist)
for j in range(1, n): # 右边的部分
for i in range(0, j): # 左边的部分 i=[0 ~ n-1]
if alist[i] > alist[j]:
alist[i], alist[j] = alist[j], alist[i]
return alist
if __name__ == "__main__":
i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
print(i)
上面这种是错的,插入排序的思想是右边 无序部分 的值和左边 有序部分 的值的比较,而且是从左边 有序部分 的右边开始。因此应该改成这样:
# coding:utf-8
def insert_sort(alist):
"""插入排序"""
n = len(alist)
for j in range(1, n): # 右边的部分
for i in range(j, 0, -1):
if alist[i] > alist[j]:
alist[i], alist[j] = alist[j], alist[i]
return alist
if __name__ == "__main__":
i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
print(i)
优化:
# coding:utf-8
def insert_sort(alist):
"""插入排序"""
n = len(alist)
for j in range(1, n): # 右边的部分
i = j
while i > 0:
if alist[i-1] > alist[i]:
alist[i-1], alist[i] = alist[i], alist[i-1]
i -= 1
else:
break
return alist
if __name__ == "__main__":
i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
print(i)
时间复杂度
- 最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
- 最坏时间复杂度:O(n2)
- 稳定性:稳定
希尔排序
# coding:utf-8
def shell_sort(alist):
"""希尔排序"""
n = len(alist)
gap = n//2 # 取对半
while gap > 0:
# 插入算法,与普通的插入算法的区别就是步长gap
for j in range(gap, n):
# j = [gap, gap+1, gap+2, gap+3]
i = j
while i > 0:
if alist[i] < alist[i-gap]:
alist[i], alist[i-gap] = alist[i-gap], alist[i]
i -= gap
else:
break
# 缩短gap步长
gap //= 2
return alist
if __name__ == "__main__":
i = shell_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
print(i)
时间复杂度
- 最优时间复杂度:根据步长序列的不同而不同
- 最坏时间复杂度:O(n2)
- 稳定想:不稳定
快速排序
# coding:utf-8
def quick_sort(alist, first, last):
"""快速排序"""
if first >= last:
return
mid_value = alist[first]
low = first
high = last
while low < high:
while low < high and alist[high] >= mid_value:
high -= 1
alist[low] = alist[high]
# low 右移
while low < high and alist[low] < mid_value:
low += 1
alist[high] = alist[low]
# 从循环退出时, low=high
alist[low] = mid_value
# 对low左边的列表排序
quick_sort(alist, first, low-1) # 对同一个列表的操作,写成这样"quick_sort(alist[:low-1])"相当于传入新的列表
# 对low右边的列表排序
quick_sort(alist, low+1, last)
if __name__ == "__main__":
li = [1, 3, 7, 2, 8, 9, 4, 5, 0, 6]
quick_sort(li, 0, len(li)-1)
print(li)
时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定
归并排序
# coding:utf-8
def merge_sort(alist):
"""归并排序"""
n = len(alist)
if n <=1:
return alist
min = n//2
# left 采用归并排序后形成的新的有序的列表
left_li = merge_sort(alist[:min])
# right 采用归并排序后形成的新的有序的列表
right_li = merge_sort(alist[min:])
# 将两个有序的子序列合并为一个新的整体
# 左右列表的两个指针
left_pointer, right_pointer = 0, 0
# 存放结果的列表
result = []
while left_pointer < len(left_li) and right_pointer < len(right_li):
if left_li[left_pointer] <= right_li[right_pointer]: # 加等于号 = 是为了遇到相等值时,前面的值还是在前面(稳定)
result.append(left_li[left_pointer])
left_pointer += 1
# elif left_li[left_pointer] > right_li[right_pointer]:
else:
result.append(right_li[right_pointer])
right_pointer += 1
# 不管左边还是右边走到头,退出循环,然后把与之对应的那一边的最后一个值加进来
result += left_li[left_pointer:]
result += right_li[right_pointer:]
return result
if __name__ == "__main__":
i = merge_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
print(i)
易于理解的版本
def merge_sort(alist):
if len(alist) <= 1:
return alist
# 二分分解
num = len(alist)/2
left = merge_sort(alist[:num])
right = merge_sort(alist[num:])
# 合并
return merge(left,right)
def merge(left, right):
'''合并操作,将两个有序数组left[]和right[]合并成一个大的有序数组'''
#left与right的下标指针
l, r = 0, 0
result = []
while l<len(left) and r<len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += left[l:]
result += right[r:]
return result
alist = [54,26,93,17,77,31,44,55,20]
sorted_alist = mergeSort(alist)
print(sorted_alist)
时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(nlogn)
- 稳定性:稳定
二分查找
# coding:utf-8
def binary_search(alist, item):
"""二分查找 递归"""
n = len(alist)
if n > 0:
min = n//2
if item == alist[min]:
return True
elif item < alist[min]:
return binary_search(alist[:min], item)
else:
return binary_search(alist[min+1:], item)
else:
return False
def binary_search2(alist, item):
"""二分查找 非递归"""
n = len(alist)
first = 0
last = n-1
while first <= last:
min = (first + last)//2
if item == alist[min]:
return True
elif item < alist[min]:
last = min -1
else:
first = min + 1
return False
if __name__ == "__main__":
print(binary_search([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 5))
print(binary_search([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10))
print(binary_search2([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 5))
print(binary_search2([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10))
时间复杂度
- 最优时间复杂度:O(1)
- 最坏时间复杂度:O(logn)
二叉树的定义和广度优先遍历和深度优先遍历
# coding:utf-8
class Node(object):
"""树的节点"""
def __init__(self, item):
self.elem = item
self.lchild = None
self.rchild = None
class Tree(object):
"""二叉树"""
def __init__(self):
self.root = None
def add(self, item):
"""树的插入"""
node = Node(item)
if self.root is None:
self.root = node
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
if cur_node.lchild is None:
cur_node.lchild = node
break
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild = node
break
else:
queue.append(cur_node.rchild)
def breadth_travel(self):
"""广度遍历"""
if self.root is None:
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
print(cur_node.elem, end=" ")
if cur_node.lchild is not None:
queue.append(cur_node.lchild)
if cur_node.rchild is not None:
queue.append(cur_node.rchild)
def preorder(self, node):
"""先序遍历"""
if node is None:
return
print(node.elem, end=" ")
self.preorder(node.lchild)
self.preorder(node.rchild)
def inorder(self, node):
"""中序遍历"""
if node is None:
return
self.inorder(node.lchild)
print(node.elem, end=" ")
self.inorder(node.rchild)
def postorder(self, node):
"""后序遍历"""
if node is None:
return
self.postorder(node.lchild)
self.postorder(node.rchild)
print(node.elem, end=" ")
if __name__ == "__main__":
tree = Tree()
tree.add(0)
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
tree.breadth_travel()
print("\n")
tree.preorder(tree.root)
print("\n")
tree.inorder(tree.root)
print("\n")
tree.postorder(tree.root)