2 - 查找算法
一、顺序查找法
1、使用Python内置的函数实现线性查找功能
"""使用Python内置的函数实现线性查找功能""" aList=[1,2,3,4,5,6,3,8,9] print(5 in aList ) #查找5是否在列表中 print(aList.index(5)) #返回第一个数据5的下标 print(aList.index(5,4,10)) #返回从下标4到10(不包含) 查找数据5 print(aList.count(5) ) #返回数据5的个数
2、不使用内置函数实现线性查找功能
""" 算法场景:给定一个整数s和一个整数数组a,判断s是否在a中,要求不用Python自带的"if s in a"语句 解决思路:要判断s是否在a中,需要逐个访问a中的元素并和s进行比较,一旦找到就返回True,如果a遍历完了还没找到s则返回False """ class Search: def seq_search(self,s,a): for i in range(len(a)): if s == a[i]: return True return False if __name__ == '__main__': a1 = [13,42,3,4,7,5,6] s1 = 7 a2 = [10, 25, 3, 4, 780, 5, 6] s2 = 70 search = Search() print(search.seq_search(s1,a1)) print(search.seq_search(s2,a2))
算法实战1:在列表alist中查找数字2
aList=[1,2,3,4,5,6,3,8,9] sign=False #初始值为没找到 x=int(input("请输入要查找的整数:")) for i in range(len(aList)): if aList[i]==x: print("整数%d在列表中,在第%d个数"%(x,i+1)) sign=True if sign==False: print("整数%d不在列表中"%x)
算法实战2: 找出列表testlist中的最大值和最小值
def Max(alist): pos = 0 #初始位置 imax=alist[0] #假设第一个元素是最大值 while pos < len(alist): #在列表中循环 if alist[pos] > imax: #当前列表的值大于最大值 ,则为最大值 imax=alist[pos] pos = pos+1 #查找位置 +1 return imax def Min(alist): pos = 0 # 初始位置 imin = alist[0] #假设第一个元素是最小值 for item in alist: #对于列表中的每一个值 if item < imin: #当前的值小于最小的值 则为最小值 imin = item return imin def main(): testlist=[2,3,4,5,6,8,34,23,55,234] print('最大值是:',Max(testlist)) print('最小值是:',Min(testlist)) if __name__=='__main__': main()
算法实战3:查找数字7在列表values中的位置
# 待查找数据集合 value # 查找的值 key def linear(value, key): # 从头到尾遍历待查找数据 for i in range(len(value)): if value[i] == key: # 成功,返回下标值 return i else: # 失败,返回-1 return -1 values = [9, 1,11, 3, 2, 6, 12, 5, 4, 7, 8, 10, 13] # 查找 7 result = linear(values, 7) if result == -1: print('查找失败') else: print('查找成功,对于下标:',result)
二、折半查找法
前提:列表有序
1、递归方式:
""" 前提:列表有序 low:查找区间的第一个下标 high:查找区间的最后一个下标 array:要查找的有序列表 key:要查找的关键字 //: 两数相除取商 %:两数相除取余数 /:两数相除取正常值 比如9/2=4.5 int(4.5)=4 转换为整数 """ def BinSearch(array, key, low, high): # 确定表的中间位置 mid = int((low+high)/2) # 将中间位置关键字与待查找关键字进行比较 if key == array[mid]: # 若找到 return True if low > high: return False if key < array[mid]: return BinSearch(array, key, low, mid-1) #递归 if key > array[mid]: return BinSearch(array, key, mid+1, high) if __name__ == "__main__": array = [4, 13, 27, 38, 49, 49, 55, 65, 76, 97] ret1 = BinSearch(array, 76, 0, len(array)-1) # 通过折半查找,找到76 print(ret1) ret2 = BinSearch(array, 100, 0, len(array) - 1) # 通过折半查找,没有找到100 print(ret2)
2、非递归方式:
def binarySearch(array, key): low = 0 high = len(list) - 1 found = False # 初始默认没有找到 while low <= high and not found: mid = (low + high) // 2 if array[mid] == key: found = True else: if key < array[mid]: high = mid - 1 else: low = mid + 1 return found list = [0, 1, 2, 3, 4, 5, 6, 7, 8] print(binarySearch(list, 3)) print(binarySearch(list, 10))
三、二叉排序树插入、删除、查找、先序遍历、中序遍历和后序遍历
# -*- coding: utf-8 -*- class Node: def __init__(self, data): self.data = data self.lchild = None self.rchild = None class BST: def __init__(self, node_list): self.root = Node(node_list[0]) for data in node_list[1:]: self.insert(data) # 查找 def search(self, node, parent, data): if node is None: return False, node, parent if node.data == data: return True, node, parent if node.data > data: return self.search(node.lchild, node, data) else: return self.search(node.rchild, node, data) # 插入 def insert(self, data): flag, n, p = self.search(self.root, self.root, data) if not flag: new_node = Node(data) if data > p.data: p.rchild = new_node else: p.lchild = new_node # 删除 def delete(self, root, data): flag, n, p = self.search(root, root, data) if flag is False: print("无该关键字,删除失败") else: if n.lchild is None: if n == p.lchild: p.lchild = n.rchild else: p.rchild = n.rchild del p elif n.rchild is None: if n == p.lchild: p.lchild = n.lchild else: p.rchild = n.lchild del p else: # 左右子树均不为空 pre = n.rchild if pre.lchild is None: n.data = pre.data n.rchild = pre.rchild del pre else: next = pre.lchild while next.lchild is not None: pre = next next = next.lchild n.data = next.data pre.lchild = next.rchild del p # 先序遍历 def preOrderTraverse(self, node): if node is not None: print(node.data,) self.preOrderTraverse(node.lchild) self.preOrderTraverse(node.rchild) # 中序遍历 def inOrderTraverse(self, node): if node is not None: self.inOrderTraverse(node.lchild) print(node.data,) self.inOrderTraverse(node.rchild) # 后序遍历 def postOrderTraverse(self, node): if node is not None: self.postOrderTraverse(node.lchild) self.postOrderTraverse(node.rchild) print(node.data,) a = [49, 38, 65, 97, 60, 76, 13, 27, 5, 1] bst = BST(a) # 创建二叉查找树 bst.inOrderTraverse(bst.root) # 中序遍历 bst.delete(bst.root, 49) print(bst.inOrderTraverse(bst.root))
四、平衡二叉树的插入、删除和查找
# -*- coding: utf-8 -*- class AVLTree(object): def info(self): a = []; for x in self: a.append(x); print(a); def __iter__(self): if self.root != None: return self.root.__iter__() else: return [].__iter__() def __contains__(self, val): for x in self: if (x == val): return True; return False; def __len__(self): a = []; for x in self: a.append(x); return len(a); class __AVLNode(object): def __init__(self, key, height=0, left=None, right=None): self.key = key self.left = left self.right = right self.height = 0 def __iter__(self): if self.left != None: for elem in self.left: yield elem if (self.key != None): yield self.key if self.right != None: for elem in self.right: yield elem # 迭代的是Node类型,用于删除结点 def iternodes(self): if self.left != None: for elem in self.left.iternodes(): yield elem if self != None and self.key != None: yield self if self.right != None: for elem in self.right.iternodes(): yield elem def info(self): s = 'Key=' + str(self.key) + ', ' + \ 'LChild=' + str(self.left) + ', ' + \ 'RChild=' + str(self.right) + ', ' + \ 'H=' + str(self.height); print(s); def __str__(self): return str(self.key); def __repr__(self): if self != None: s_1 = str(self.key); else: s_1 = 'None'; if self.left != None: s_2 = str(self.left.key); else: s_2 = 'None'; if self.right != None: s_3 = str(self.right.key); else: s_3 = 'None'; s_4 = str(self.height); return '__AVLNode(' + s_1 + ', ' + s_2 + ', ' + s_3 + ', ' + s_4 + ')'; def __init__(self): self.root = None def find(self, key): if self.root is None: return None else: return self._find(key, self.root) def _find(self, key, node): if node is None: return None elif key < node.key: return self._find(key, self.left) elif key > node.key: return self._find(key, self.right) else: return node # 找最小元素 def findMin(self): if self.root is None: return None else: return self._findMin(self.root) def _findMin(self, node): if node.left: return self._findMin(node.left) else: return node # 找最大元素 def findMax(self): if self.root is None: return None else: return self._findMax(self.root) def _findMax(self, node): if node.right: return self._findMax(node.right) else: return node # 求结点高度 def height(self, node): if (node == None): return 0; else: m = self.height(node.left); n = self.height(node.right); return max(m, n) + 1; # LL def singleLeftRotate(self, node): k1 = node.left node.left = k1.right k1.right = node node.height = max(self.height(node.right), self.height(node.left)) + 1 k1.height = max(self.height(k1.left), node.height) + 1 return k1 # RR def singleRightRotate(self, node): k1 = node.right node.right = k1.left k1.left = node node.height = max(self.height(node.right), self.height(node.left)) + 1 k1.height = max(self.height(k1.right), node.height) + 1 return k1 # LR def doubleLeftRotate(self, node): node.left = self.singleRightRotate(node.left) return self.singleLeftRotate(node) # RL def doubleRightRotate(self, node): node.right = self.singleLeftRotate(node.right) return self.singleRightRotate(node) # 插入 def insert(self, key): if not self.root: self.root = AVLTree.__AVLNode(key) else: self.root = self._insert(self.root, key) def _insert(self, node, key): if node is None: node = AVLTree.__AVLNode(key) elif key < node.key: node.left = self._insert(node.left, key) if (self.height(node.left) - self.height(node.right)) == 2: if key < node.left.key: node = self.singleLeftRotate(node) else: node = self.doubleLeftRotate(node) elif key > node.key: node.right = self._insert(node.right, key) if (self.height(node.right) - self.height(node.left)) == 2: if key < node.right.key: node = self.doubleRightRotate(node) else: node = self.singleRightRotate(node) node.height = max(self.height(node.right), self.height(node.left)) + 1 return node # 删除 def delete(self, key): if key in self: self.root = self.remove(key, self.root) def remove(self, key, node): if node is None: raise KeyError('Error,key not in tree'); elif key < node.key: node.left = self.remove(key, node.left) if (self.height(node.right) - self.height(node.left)) == 2: if self.height(node.right.right) >= self.height(node.right.left): node = self.singleRightRotate(node) else: node = self.doubleRightRotate(node) node.height = max(self.height(node.left), self.height(node.right)) + 1 elif key > node.key: node.right = self.remove(key, node.right) if (self.height(node.left) - self.height(node.right)) == 2: if self.height(node.left.left) >= self.height(node.left.right): node = self.singleLeftRotate(node) else: node = self.doubleLeftRotate(node) node.height = max(self.height(node.left), self.height(node.right)) + 1 elif node.left and node.right: if node.left.height <= node.right.height: minNode = self._findMin(node.right) node.key = minNode.key node.right = self.remove(node.key, node.right) else: maxNode = self._findMax(node.left) node.key = maxNode.key node.left = self.remove(node.key, node.left) node.height = max(self.height(node.left), self.height(node.right)) + 1 else: if node.right: node = node.right else: node = node.left return node # 传回结点的原始信息 def iternodes(self): if self.root != None: return self.root.iternodes() else: return [None]; # 寻找节点路径 def findNodePath(self, root, node): path = []; if root == None or root.key == None: path = []; return path while (root != node): if node.key < root.key: path.append(root); root = root.left; elif node.key >= root.key: path.append(root); root = root.right; else: break; path.append(root); return path; # 寻找父结点 def parent(self, root, node): path = self.findNodePath(root, node); if (len(path) > 1): return path[-2]; else: return None; # 是否左孩子 def isLChild(self, parent, lChild): if (parent.getLeft() != None and parent.getLeft() == lChild): return True; return False; # 是否右孩子 def isRChild(self, parent, rChild): if (parent.getRight() != None and parent.getRight() == rChild): return True; return False; # 求某元素是在树的第几层 # 约定根为0层 # 这个计算和求结点的Height是不一样的 def level(self, elem): if self.root != None: node = self.root; lev = 0; while (node != None): if elem < node.key: node = node.left; lev += 1; elif elem > node.key: node = node.right; lev += 1; else: return lev; return -1; else: return -1; if __name__ == '__main__': avl = AVLTree(); a = [20, 30, 40, 120, 13, 39, 38, 40, 18, 101]; b = [[10, 1], [3, 0], [4, 0], [13, -1], [2, 0], [18, 0], [40, -1], [39, 0], [12, 0]]; for item in b: avl.insert(item); avl.info(); print(45 in avl); print(len(avl)); ''' avl.delete(40); avl.info(); avl.delete(100); avl.info(); avl.insert(1001); avl.info(); ''' for item in avl.iternodes(): item.info(); print(avl.findNodePath(avl.root, item)); print('Parent:', avl.parent(avl.root, item)); print('Level:', avl.level(item.key)); print('\n');