Python__数据结构与算法——查找与排序

 

查找和排序是最基本的算法,在很多脚本中都会用到查找和排序。尽管 Python 提供的用于查找和排序的函数能够满足绝大多数需求,但还是有必要了解最基本的查找和排序算法,以便在有特殊需求的情况下,可以自己编写查找、排序脚本。

一、查找

基本的查找方法有顺序查找、二分查找和分块查找等。其中,顺序查找是最简单的查找方法,就是按照数据排列的顺序依次查找,直到找到所查找的数据为止(可查看数据表都未找到数据)。

二分查找是首先对要进行查找的数据进行排序,有按大小顺序排好的 9 个数字,如图-1所示。如果要进行查找数字 5,则首先与中间值 10 进行比较,5 小于 10,于是对序列的前半部分 1~9 进行查找。此时,中间值为 5,恰好为要找的数字,查找结束。

分块查找,是介于顺序查找和二分查找之间的一种查找方法。使用分块查找时,首先对查找表建立一个索引表,然后再进行分块查找。建立索引表时,首先对查找表进行分块,要求 "分块有序",即块内关键字不一定有序,但分块之间有大小顺序。索引表是抽取各块中的最大关键字及其起始位置构成的,如图-2 所示。

分块查找分两步进行,首先查找索引表,因为索引表是有序的,查找索引表时可以使用二分查找法进行。查找完索引表以后,就确定了要查找的数据所在的分块,然后在该分块中再进行顺序查找。

下面所示的 pyBinarySearch.py 脚本是对一个有序列表使用二分查找。

# -*- coding:UTF-8 -*-
# file: pyBinarySearch.py


def BinarySearch(l, key):  # 二分查找
    low = 0
    high = len(l) - 1
    i = 0
    while low <= high:
        i = i + 1
        mid = (high + low) // 2
        if l[mid] < key:
            low = mid + 1
        elif l[mid] > key:
            high = mid - 1
        else:
            print('use %d time(s)' % i)
            return mid
    return -1


if __name__ == '__main__':
    l = [1, 5, 6, 9, 10, 51, 62, 65, 70]  # 构造列表
    print(BinarySearch(l, 5))  # 在列表中查找
    print(BinarySearch(l, 10))
    print(BinarySearch(l, 65))
    print(BinarySearch(l, 70))

运行脚本输出结果如下:

二、排序

对于查找来说,排序要复杂得多,排序的方法也较多,常用的排序方法有冒泡法排序、希尔排序、二叉树排序和快速排序等,其中,二叉树排序是比较有意思的一种排序方法,而且也便于操作。二叉树排序的过程主要是二叉树的建立和遍历的过程。例如,有一组数据 "3,5,7,20,43,2,15,30",则二叉树的建立过程如下。

  • Step1:首先将第一个数据 3 放入根节点。
  • Step2:将数据 5 与根节点中的数据 3 比较,由于 5 大于 3,因此应将 5 放入 3 的右子树中。
  • Step3:将数据 7 与根节点中的数据 3 比较,由于 7 大于 3,因此应将 5 放入 3 的右子树中,由于 3 已经有右儿子 5,所以将 7 与 5 进行比较,因为 7 大于 5,所以应将 7 放入 5 的右子树中。
  • Step4:将数据 20 与根节点中的数据 3 比较,由于 20 大于 3,因此应将 20 放入 3 的右子树中,重复比较,最终将 20 放入 7 的右子树中。
  • Step5:将数据 43 与树中的节点值进行比较,最终将其放入 20 的右子树中。
  • Step6:将数据 2 与根节点 3 进行比较,由于 2 小于 3,因此应将 2 放入 3 的左子树。
  • Step7:同样的对数据 15 和 30 进行处理,最终形成如图-3 所示的树。

当树创建好后,对数进行中序遍历,得到的遍历结果就是对数据从小到大排序。如果要从大到小进行排序则可以先从右子树开始进行中序遍历。

下面所示的 pySort.py 脚本是采用二叉树排序的方式对数据进行排序。

# -*- coding:UTF-8 -*-
# file: pySort.py


class BTree:  # 二叉树节点
    def __init__(self, value):  # 初始化函数
        self.left = None  # 左儿子
        self.data = value  # 节点值
        self.right = None  # 右儿子

    def insertLeft(self, value):  # 向左子树插入节点
        self.left = BTree(value)
        return self.left

    def insertRight(self, value):  # 向右子树插入节点
        self.right = BTree(value)
        return self.right

    def show(self):  # 输出节点数据
        print(self.data)


def inorder(node):  # 中序遍历
    if node.data:
        if node.left:
            inorder(node.left)
        node.show()
        if node.right:
            inorder(node.right)


def rinorder(node):  # 中序遍历
    if node.data:
        if node.right:
            rinorder(node.right)
        node.show()
        if node.left:
            rinorder(node.left)


def insert(node, value):  # 中序遍历,先遍历右子树
    if value > node.data:
        if node.right:
            insert(node.right, value)
        else:
            node.insertRight(value)
    else:
        if node.left:
            insert(node.left, value)
        else:
            node.insertLeft(value)


if __name__ == '__main__':
    l = [3, 5, 7, 20, 43, 2, 15, 30]
    Root = BTree(l[0])  # 根节点
    node = Root
    for i in range(1,len(l)):
        insert(Root, l[i])
    print('**************************')
    print('        从小到大')
    print('**************************')
    inorder(Root)
    print('**************************')
    print('        从大到小')
    print('**************************')
    rinorder(Root)

运行 pySort.py 脚本后,输出如下所示的排序结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值