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');

 

posted @ 2022-09-12 16:08  xiaoyanhahaha  阅读(62)  评论(0编辑  收藏  举报