查找
- 既希望较快的查找又便于线性表动态变化的查找方法是哈希法查找。二叉排序树查找,最优二叉树查找,键树查找,哈希法查找是动态查找。分块、顺序、折半、索引顺序查找均为静态。分块法应该是将整个线性表分成若干块进行保存,若动态变化则可以添加在表的尾部(非顺序结构),时间复杂度是O(1),查找复杂度为O(n);若每个表内部为顺序结构,则可用二分法将查找时间复杂度降至O(logn),但同时动态变化复杂度则变成O(n);顺序法是挨个查找,这种方法最容易实现,不过查找时间复杂度都是O(n),动态变化时可将保存值放入线性表尾部,则时间复杂度为O(1);二分法是基于顺序表的一种查找方式,时间复杂度为O(logn);通过哈希函数将值转化成存放该值的目标地址,O(1)
- 二叉树的平均查找长度为O(log2n)——O(n).二叉排序树的查找效率与二叉树的高度有关,高度越低,查找效率越高。二叉树的查找成功的平均查找长度ASL不超过二叉树的高度。二叉树的高度与二叉树的形态有关,n个节点的完全二叉树高度最小,高度为[log2n]+1,n个节点的单只二叉树的高度最大,高度为n,此时查找成功的ASL为最大(n+1)/2,因此二叉树的高度范围为[log2n]+1——n.
- 链式存储不能随机访问,必须是顺序存储
https://cuijiahua.com/blog/2018/01/algorithm_6.html
快排:数据越随机,效果越好
冒泡:数据越有序,效果越好
一、冒泡排序(交换排序)
思想:重复的走访要排序的数列,一次比较两个元素。如果顺序错误就交换,直到没有需要交换的元素。
优化:加入标志性变量exchange(吧),用于标志某一趟排序过程是否有数据交换。
code:
def bubble_sort(list):
for i in range(len(list)-1):
b = False
print('第%d趟排序:' % (i + 1))
for j in range(len(list)-1):
if list[j] > list[j+1]:
a = list[j]
list[j] = list[j+1]
list[j+1] = a
b = True
print(list)
if not b:
break
return list
my_list = [12,1,5,23,8,2,8,3,89,4,5,7,23,7]
print(bubble_sort(my_list))
运行结果:
二、直接插入排序(插入排序)
思想:每一趟将一个待排序的数字插入到有序序列中,直到全部插入完成。
优化:在有序序列中插入一个数,可用二分查找,减少元素比较次数提高效率。
code:
def insert_sort(list):
if len(list) == 0:
return []
sorted_list = list
for i in range(1, len(sorted_list)):
temp = sorted_list[i]
j = i - 1
while j >= 0 and temp < sorted_list[j]:
sorted_list[j+1] = sorted_list[j]
j = j-1
sorted_list[j + 1] = temp
return sorted_list
my_list = [3,2,5,9,8,6]
print(insert_sort(my_list))
运行结果:
优化:
def binary_search(list, end, item):
low = 0
high = end - 1
while low <= high:
mid = int((low + high)/2)
guess = list[mid]
if guess <= item:
low = mid + 1
else:
high = mid-1
return low if low < end else -1
def insert_sort(list):
if len(list) == 0:
return []
sorted_list = list
for i in range(1, len(list)):
j =i-1
temp = sorted_list[i]
index = binary_search(list, i, temp)
while index != -1 and j >= index:
sorted_list[j+1] = sorted_list[j]
j -= 1
sorted_list[j+1] = temp
return sorted_list
my_list = [3,2,5,9,8,6]
print(insert_sort(my_list))
三:希尔排序(插入排序)
思想:对要排序的序列,先以步长5(步长选择自由,这里只是举例说明)对序列按行进行分割,然后按列进行排序;对得到的序列以步长3分割,按列排序‘最后步长为1排序。
code:
def shell_sort(arr):
if len(arr) <= 1:
return arr
length = len(arr)
gap = length // 2
while gap > 0:
for i in range(gap, length):
j = i - gap
temp = arr[i]
while j >= 0 and arr[j] > temp:
arr[j + gap] = arr[j]
j -= gap
arr[j+gap] = temp
gap //= 2
return arr
my_list = [3,2,5,9,8,6]
print(shell_sort(my_list))
四:快速排序(交换排序)
思想:分而治之。通过排序将序列分割为两部分,左边都是比基线条件小的数,右边都是比它大的数;然后再按照这个方法对分割后的两个序列排序,使用递归进行快速排序。
code:
def quicksort(arr):
if len(arr) < 1:
return arr
else:
median = arr[0]
less = [i for i in arr[1:] if i <= median]
greater = [i for i in arr[1:] if i > median]
return quicksort(less) + [median] + quicksort(greater)
my_arr = [3,2,6,8,4,3,1,2,0]
print(quicksort(my_arr))
五:简单选择排序(选择排序)
思想:每趟从待排序的序列中选出最小的数,顺序放在以排序的序列末尾,直到全部排序为止。
code:
def findsmallest(arr):
smallest = arr[0]
smallest_index = 0
for i in range(len(arr)):
if smallest > arr[i]:
smallest = arr[i]
smallest_index = i
return smallest_index
def selectionsort(arr):
newarr = []
for i in range(len(arr)):
smallest = findsmallest(arr)
newarr.append(arr.pop(smallest))
return newarr
print(selectionsort([2,5,7,8,6]))
六:堆排序(选择排序)
思想:堆排序是利用堆的性质进行的一种选择排序。
当想得到一个序列中第k个最小的元素之前的部分排序序列,最好采用堆排序。
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 20 18:13:01 2019
@author: AAA
"""
def HeadSort(input_list):
'''
函数说明:堆排序(升序)
Author:
www.cuijiahua.com
Parameters:
input_list - 待排序列表
Returns:
sorted_list - 升序排序好的列表
'''
def HeadAdjust(input_list, parent, length):
'''
函数说明:堆调整,调整为最大堆
Author:
www.cuijiahua.com
Parameters:
input_list - 待排序列表
parent - 堆的父结点
length - 数组长度
Returns:
无
'''
temp = input_list[parent]
child = 2 * parent + 1
while child < length:
if child + 1 < length and input_list[child] < input_list[child+1]:
child += 1
if temp >= input_list[child]:
break
input_list[parent] = input_list[child]
parent = child
child = 2 * parent + 1
input_list[parent] = temp
if len(input_list) == 0:
return []
sorted_list = input_list
length = len(sorted_list)
for i in range(0, length // 2)[::-1]:
HeadAdjust(sorted_list, i, length)
for j in range(1, length)[::-1]:
temp = sorted_list[j]
sorted_list[j] = sorted_list[0]
sorted_list[0] = temp
HeadAdjust(sorted_list, 0, j)
print('第%d趟排序:' % (length - j), end = '')
print(sorted_list)
return sorted_list
if __name__ == '__main__':
input_list = [6, 4, 8, 7, 9, 2, 3, 1]
print('排序前:', input_list)
sorted_list = HeadSort(input_list)
print('排序后:', sorted_list)
七:归并排序
思想:分而治之
归并排序采用分而治之的原理:
一、将一个序列从中间位置分成两个序列;
二、在将这两个子序列按照第一步继续二分下去;
三、直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。
# -*- coding:utf-8 -*-
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr)//2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(a, b):
c = []
i = 0
j = 0
while i < len(a) and j < len(b):
if a[i] < b[j]:
c.append(a[i])
i += 1
else:
c.append(b[j])
j += 1
if i == len(a):
for ii in b[j:]:
c.append(ii)
elif j == len(b):
for jj in a[i:]:
c.append(jj)
return c
if __name__ == '__main__':
merge_sort([2,4,6,2,1,123,57])
八:基数排序(非比较型整数排序算法)
参考:https://blog.csdn.net/weixin_40924580/article/details/83999964
# -*- coding: utf-8 -*-
"""
Created on Thu Feb 21 13:37:30 2019
@author: AAA
"""
def RadixSort(input_list):
i = 0 #初始为个位排序
n = 1 #最小的位数置为1(包含0)
max_num = max(input_list) #得到带排序数组中最大数
while max_num > 10**n: #得到最大数是几位数
n += 1
while i < n:
bucket = {} #用字典构建桶
for x in range(10):
bucket.setdefault(x, []) #将每个桶置空
for x in input_list: #对每一位进行排序
radix =int((x / (10**i)) % 10) #得到每位的基数
bucket[radix].append(x) #将对应的数组元素加入到相应位基数的桶中
j = 0
for k in range(10):
if len(bucket[k]) != 0: #若桶不为空
for y in bucket[k]: #将该桶中每个元素
input_list[j] = y #放回到数组中
j += 1
i += 1
return input_list
if __name__ == '__main__':
input_list = [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
print('排序前:', input_list)
sorted_list = RadixSort(input_list)
print('排序后:', sorted_list)