Python入门系列四-数据结构与算法基础

在编程中,数据结构和算法是我们处理数据的基础工具。了解常用的数据结构和算法,能够帮助我们更高效地存储、操作和查找数据。本文将介绍Python中的常见数据结构(如列表、元组、字典、集合等)、常用的线性数据结构(栈、队列、链表)以及基本的排序和查找算法,帮助你掌握如何在不同场景中选择合适的数据结构和算法。

1. 列表、元组、字典、集合的应用

1.1 列表(List)

列表是Python中最常用的数据结构之一,它是一个有序的元素集合,可以包含任意类型的数据。列表是可变的,可以动态地修改。

  • 创建列表 :通过[]或者list()函数创建。
  • 访问列表元素:可以通过索引访问列表中的元素。
  • 修改列表 :可以通过索引修改列表中的元素,或者使用append()extend()insert()等方法。
  • 删除元素 :可以使用remove()pop()或者del
python 复制代码
# 创建列表
fruits = ["apple", "banana", "cherry"]

# 访问元素
print(fruits[0])  # 输出:apple

# 修改元素
fruits[1] = "blueberry"

# 删除元素
fruits.remove("cherry")

# 输出修改后的列表
print(fruits)  # 输出:['apple', 'blueberry']
1.2 元组(Tuple)

元组是一个不可变的序列,类似于列表,但是一旦创建就不能修改。适合存储不需要更改的数据。

  • 创建元组 :通过()创建。
  • 访问元组元素:可以通过索引访问元组中的元素。
python 复制代码
# 创建元组
coordinates = (10, 20, 30)

# 访问元素
print(coordinates[1])  # 输出:20
1.3 字典(Dictionary)

字典是一个无序的键值对集合,每个键对应一个值。字典是可变的,适合用来存储具有映射关系的数据。

  • 创建字典 :通过{}或者dict()函数创建。
  • 访问元素:可以通过键来访问字典中的值。
  • 添加和修改元素:可以通过键来添加或者修改字典中的值。
python 复制代码
# 创建字典
person = {"name": "Alice", "age": 25}

# 访问元素
print(person["name"])  # 输出:Alice

# 修改元素
person["age"] = 26

# 添加元素
person["city"] = "New York"

# 输出修改后的字典
print(person)  # 输出:{'name': 'Alice', 'age': 26, 'city': 'New York'}
1.4 集合(Set)

集合是一个无序的、不重复的元素集合。集合适用于去重、集合运算等操作。

  • 创建集合 :通过{}或者set()函数创建。
  • 操作集合:可以进行并集、交集、差集等操作。
python 复制代码
# 创建集合
fruits = {"apple", "banana", "cherry"}

# 添加元素
fruits.add("orange")

# 删除元素
fruits.remove("banana")

# 输出集合
print(fruits)  # 输出:{'apple', 'cherry', 'orange'}

2. 常用数据结构:栈、队列、链表

2.1 栈(Stack)

栈是一种后进先出(LIFO,Last In First Out)结构。栈的操作主要包括:

  • 压栈(push):将元素添加到栈顶。
  • 弹栈(pop):移除并返回栈顶的元素。
  • 查看栈顶元素(peek):获取栈顶元素,但不移除它。
python 复制代码
stack = []

# 压栈
stack.append(1)
stack.append(2)
stack.append(3)

# 弹栈
top = stack.pop()
print(top)  # 输出:3

# 查看栈顶元素
print(stack[-1])  # 输出:2
2.2 队列(Queue)

队列是一种先进先出(FIFO,First In First Out)结构。队列的操作主要包括:

  • 入队(enqueue):将元素添加到队尾。
  • 出队(dequeue):移除并返回队头的元素。
python 复制代码
from collections import deque

queue = deque()

# 入队
queue.append(1)
queue.append(2)
queue.append(3)

# 出队
front = queue.popleft()
print(front)  # 输出:1
2.3 链表(Linked List)

链表是一种线性数据结构,每个元素包含数据和指向下一个元素的指针。Python没有内建的链表类型,但可以通过类和节点来实现。

python 复制代码
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class LinkedList:
    def __init__(self):
        self.head = None

    def append(self, data):
        new_node = Node(data)
        if not self.head:
            self.head = new_node
        else:
            last_node = self.head
            while last_node.next:
                last_node = last_node.next
            last_node.next = new_node

    def print_list(self):
        current_node = self.head
        while current_node:
            print(current_node.data, end=" -> ")
            current_node = current_node.next
        print("None")

# 创建链表
ll = LinkedList()
ll.append(1)
ll.append(2)
ll.append(3)

ll.print_list()  # 输出:1 -> 2 -> 3 -> None

3. 排序算法:冒泡排序、选择排序、插入排序

3.1 冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法,它重复地遍历待排序的列表,比较相邻元素并交换它们的位置,直到没有需要交换的元素为止。

python 复制代码
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]

arr = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

假设我们有一个列表:[64, 34, 25, 12, 22, 11, 90],我们将通过多次交换过程直观地展示如何排序。

步骤 1: 初始列表

[64, 34, 25, 12, 22, 11, 90]

步骤 2: 第一轮遍历,比较相邻元素并交换:

  • 64 > 34 → 交换:[34, 64, 25, 12, 22, 11, 90]
  • 64 > 25 → 交换:[34, 25, 64, 12, 22, 11, 90]
  • 64 > 12 → 交换:[34, 25, 12, 64, 22, 11, 90]
  • 64 > 22 → 交换:[34, 25, 12, 22, 64, 11, 90]
  • 64 > 11 → 交换:[34, 25, 12, 22, 11, 64, 90]
  • 64 < 90 → 不交换。

第一轮遍历后:

[34, 25, 12, 22, 11, 64, 90]

在这一轮中,最大的元素90已经被移动到了最后。

步骤 3: 第二轮遍历:

  • 34 > 25 → 交换:[25, 34, 12, 22, 11, 64, 90]
  • 34 > 12 → 交换:[25, 12, 34, 22, 11, 64, 90]
  • 34 > 22 → 交换:[25, 12, 22, 34, 11, 64, 90]
  • 34 > 11 → 交换:[25, 12, 22, 11, 34, 64, 90]
  • 34 < 64 → 不交换。

第二轮遍历后:

[25, 12, 22, 11, 34, 64, 90]

这个过程会继续进行,直到列表完全有序。最终结果会是:

[11, 12, 22, 25, 34, 64, 90]
总结

冒泡排序每次遍历时都将最大的元素"冒泡"到列表的末尾,因此其最坏时间复杂度是 O(n²)。对于较大的数据集,冒泡排序效率较低。


3.2 选择排序(Selection Sort)

选择排序每次从未排序的部分中选择最小(大)元素,并将其放到已排序部分的末尾。

python 复制代码
def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        min_idx = i
        for j in range(i+1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        arr[i], arr[min_idx] = arr[min_idx], arr[i]

arr = [64, 34, 25, 12, 22, 11, 90]
selection_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

假设我们有一个列表:[64, 34, 25, 12, 22, 11, 90],我们将通过每一轮选择最小元素并交换的位置来直观展示排序过程。

步骤 1: 初始列表

[64, 34, 25, 12, 22, 11, 90]

步骤 2: 找到最小的元素(11),并与第一个元素(64)交换:

[11, 34, 25, 12, 22, 64, 90]

步骤 3: 在剩下的部分(34, 25, 12, 22, 64, 90)中找到最小的元素(12),并与第二个元素(34)交换:

[11, 12, 25, 34, 22, 64, 90]

步骤 4: 在剩下的部分(25, 34, 22, 64, 90)中找到最小的元素(22),并与第三个元素(25)交换:

[11, 12, 22, 34, 25, 64, 90]

步骤 5: 在剩下的部分(34, 25, 64, 90)中找到最小的元素(25),并与第四个元素(34)交换:

[11, 12, 22, 25, 34, 64, 90]

步骤 6: 在剩下的部分(34, 64, 90)中找到最小的元素(34),不需要交换,因为它已经在正确的位置:

[11, 12, 22, 25, 34, 64, 90]

步骤 7: 在剩下的部分(64, 90)中找到最小的元素(64),不需要交换:

[11, 12, 22, 25, 34, 64, 90]

最终,排序完成:

[11, 12, 22, 25, 34, 64, 90]
总结

选择排序每一轮选择最小元素,因此最坏时间复杂度是 O(n²)。尽管它的实现简单,但其效率在数据量大时不高。


3.3 插入排序(Insertion Sort)

插入排序通过逐步将未排序的元素插入到已排序的部分,直到整个列表有序。

python 复制代码
def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key

arr = [64, 34, 25, 12, 22, 11, 90]
insertion_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

假设我们有一个列表:[64, 34, 25, 12, 22, 11, 90],我们将通过每一轮插入元素并移动的过程来直观展示排序。

步骤 1: 初始列表

[64, 34, 25, 12, 22, 11, 90]

步骤 2: 将第二个元素(34)插入到已排序部分([64]):

  • 34 小于 64,所以将 64 向后移动,将 34 插入到位置 0:

    [34, 64, 25, 12, 22, 11, 90]

步骤 3: 将第三个元素(25)插入到已排序部分([34, 64]):

  • 25 小于 64,先将 64 向后移动,再将 25 小于 34,所以将 34 向后移动,将 25 插入到位置 0:

    [25, 34, 64, 12, 22, 11, 90]

步骤 4: 将第四个元素(12)插入到已排序部分([25, 34, 64]):

  • 12 小于 64,34,25,所以将它们依次向后移动,将 12 插入到位置 0:

    [12, 25, 34, 64, 22, 11, 90]

步骤 5: 将第五个元素(22)插入到已排序部分([12, 25, 34, 64]):

  • 22 小于 64、34、25,所以将它们依次向后移动,将 22 插入到位置 1:

    [12, 22, 25, 34, 64, 11, 90]

步骤 6: 将第六个元素(11)插入到已排序部分([12, 22, 25, 34, 64]):

  • 11 小于 64、34、25、22、12,所以将它们依次向后移动,将 11 插入到位置 0:

    [11, 12, 22, 25, 34, 64, 90]

步骤 7: 最后一个元素(90)已经是有序的,无需插入:

[11, 12, 22, 25, 34, 64, 90]
总结

插入排序在数据量小的时候效率较高,尤其是当数据几乎有序时,插入排序能表现出接近 O(n) 的效率。最坏时间复杂度是 O(n²)


4. 查找算法:线性查找与二分查找

4.1 线性查找(Linear Search)

线性查找是最简单的查找算法,它通过逐个遍历列表来查找目标元素。

python 复制代码
def linear_search(arr, target):
    for

 i, value in enumerate(arr):
        if value == target:
            return i
    return -1

arr = [64, 34, 25, 12, 22, 11, 90]
index = linear_search(arr, 22)
print(index)  # 输出:4
4.2 二分查找(Binary Search)

二分查找是一种高效的查找方法,前提是数据必须是已排序的。它通过将列表分为两半来逐步缩小查找范围。

python 复制代码
def binary_search(arr, target):
    low, high = 0, len(arr) - 1
    while low <= high:
        mid = (low + high) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1

arr = [11, 12, 22, 25, 34, 64, 90]
index = binary_search(arr, 22)
print(index)  # 输出:2

生活就是这样,脚长在自己身上,往前走就对了,直到向往的风景,变成走过的地方

相关推荐
暗碳7 小时前
cloudns二级免费域名python更新ipv6 dns记录
开发语言·python
BlackPercy7 小时前
[paddle] 非线性拟合问题的训练
python·机器学习·paddlepaddle·paddle
N2018716438 小时前
开源GTKSystem.Windows.Forms框架:C# Winform跨平台运行深度解析
windows·开源·c#
wcyd9 小时前
如何使用Python生成词云图:结合`wordcloud`、`imageio`、`collections`和`jieba`分词模块
开发语言·python·信息可视化
ONE_PUNCH_Ge9 小时前
Python3 正则表达式
python
时间sk9 小时前
HTML——70. 多行文本输入框
html
cxr82810 小时前
基于微信小程序的面部动作检测系统
人工智能·python·算法·计算机视觉·微信小程序·小程序·视觉检测
橙子 chen10 小时前
工具函数 - 调用http
java·大数据·网络·数据库·python·网络协议·http
羊小猪~~10 小时前
基于RNN模型的心脏病预测,提供tensorflow和pytorch实现
pytorch·python·rnn·深度学习·神经网络·机器学习·tensorflow
多恩Stone10 小时前
【Triton-ONNX】如何使用 ONNX 模型服务与 Triton 通信执行推理任务上-Triton快速开始
服务器·开发语言·python·docker