数据结构--python学习 day6

一. 数据结构与算法

  • 数据结构与算法是计算机科学的两个核心概念,它们在程序设计、系统开发和软件工程中发挥着重要作用。以下是对两个概念的简要介绍:

数据结构

  • 数据结构是组织、存储和管理数据的方式。选择合适的数据结构可以提高程序的效率和可维护性。常见的数据结构包括:

      1. 数组:一组相同类型的元素的集合,可以通过索引快速访问。
      1. 链表:由节点组成的线性数据结构,每个节点包含数据和指向下一个节点的指针。
      1. :一种后进先出(LIFO)的数据结构,允许在一端插入和删除元素。
      1. 队列:一种先进先出(FIFO)的数据结构,允许在一端插入元素,在另一端删除元素。
      1. 哈希表:通过哈希函数将键映射到值,提供快速的查找、插入和删除操作。
      1. :一种分层数据结构,最常用的是二叉树和二叉搜索树,也有平衡树(如AVL树和红黑树)。
      1. :由节点(顶点)和边组成,可以表示各种关系。

算法

算法是解决特定问题的一系列步骤或规则。算法的效率和性能通常通过时间复杂度和空间复杂度来衡量。常见的算法类型包括:

  1. 排序算法:对于数据进行排序的算法,如快速排序、归并排序和冒泡排序。
  2. 搜索算法:在数据结构中查找特定元素的算法,如二分搜索和线性搜索。
  3. 图算法:用于操作图的算法,如深度优先搜索(DFS)、广度优先搜索(BFS)、最短路径算法(如Dijkstra算法)和最小生成树算法(如Kruskal和Prim算法)。
  4. 动态规划:解决复杂问题的方法,通过将问题分解为更小的子问题并保存其结果来改善效率。
  5. 贪心算法:通过局部最优解来构建全局最优解的方法,通常用于优化问题。

二.列表

创建一个空的列表

 list = [ ]
 L = ['北京', '上海', '广州', '西安']  # 创建一个含有4个字符串的列表
  • 创建列表的函数
list()
list(可迭代对象)
  • 列表的常用方法
运算结果
s.index(x[, i[, j]])xs 中首次出现项的索引号(索引号在 i 或其后且在 j 之前)
s.count(x)xs 中出现的总次数
s.append(x)x 添加到序列的末尾 (等同于 s[len(s):len(s)] = [x])
s.clear()s 中移除所有项 (等同于 del s[:])
s.copy()创建 s 的浅拷贝 (等同于 s[:])
s.extend(t)s += tt 的内容扩展 s (基本上等同于 s[len(s):len(s)] = t)
s.insert(i, x)在由 i 给出的索引位置将 x 插入 s (等同于 s[i:i] = [x])
s.pop([i])提取在 i 位置上的项,并将其从 s 中移除
s.remove(x)删除 s 中第一个 s[i] 等于 x 的项目。
s.reverse()就地将列表中的元素逆序。
s.sort( key=None, *reverse=False*)对列表内的数据进行排序, reverse=False 升序排序,否则是降序排序

三.集合

  • 创建集合
    创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
s1 = {10, 20, 30}
print(len(s1))
  • 集合(set)没有索引查看的功能。集合是一种无序、不可重复的数据结构,用于存储唯一的元素。由于集合是无序的,所以不能通过索引来访问其中的元素。所以也没有对应的修改功能。

  • 常用方法

方法描述
add()为集合添加元素
clear()移除集合中的所有元素
copy()拷贝一个集合
difference()返回多个集合的差集
difference_update()移除集合中的元素,该元素在指定的集合也存在。
discard()删除集合中指定的元素
intersection()返回集合的交集
intersection_update()返回集合的交集。
isdisjoint()判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False。
issubset()判断指定集合是否为该方法参数集合的子集。
issuperset()判断该方法的参数集合是否为指定集合的子集
pop()随机移除元素
remove()移除指定元素
symmetric_difference()返回两个集合中不重复的元素集合。
symmetric_difference_update()移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。
union()返回两个集合的并集
update()给集合添加元素
len()计算集合元素个数

四.字典

  • 字典的创建

字典的表示方式以 {} 括起来, 以英文的冒号 ( : ) 分隔键值对,各键值对之间用逗号(,)分隔

d = {}    # 创建空字典
d = {'name': "weimingze", "age": 35}
d = {'a': [1, 2, 3]}
d = {'b': {"bb": 222}}
  • 注:

    • 键必须是唯一的,但值则不必。

    • 值可以取任何数据类型,但键必须是不可变的,如字符串,数字

  • 字典的方法:

序号函数及描述
1dict.clear()删除字典内所有元素
2dict.copy()返回一个字典的浅复制
3dict.fromkeys(seq)创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值
4dict.get(key, default=None)返回指定键的值,如果键不在字典中返回 default 设置的默认值
5key in dict如果键在字典dict里返回true,否则返回false
6dict.items()以列表返回一个视图对象
7dict.keys()返回一个视图对象
8dict.setdefault(key, default=None)和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
9dict.update(dict2)把字典dict2的键/值对更新到dict里
10dict.values()返回一个视图对象
11pop(key,default)删除字典 key(键)所对应的值,返回被删除的值。
12popitem()返回并删除字典中的最后一对键和值。

五.栈–Stack

  • 栈(Stack)是一种线性数据结构,它遵循后进先出(LIFO,Last In First Out)的原则。也就是说,最后放入栈中的元素最先被取出。栈的基本操作通常包括入栈(Push)、出栈(Pop)、查看栈顶元素(Peek或Top)和检查栈是否为空(IsEmpty)。

栈的基本操作

  1. 入栈(Push):将一个元素压入栈顶。
  2. 出栈(Pop):从栈顶移除一个元素并返回这个元素。
  3. 查看栈顶元素(Peek/Top):返回栈顶元素,但不移除它。
  4. 检查栈空(IsEmpty):判断栈是否为空。

栈的特点

  • 顺序性:栈中的元素在特定的顺序中排列。

  • 限制性:只能在栈顶进行插入和删除操作。

  • 内存结构:可以使用数组或链表实现。

  • 栈常见的操作

    • push(element): 添加一个新元素到栈顶位置.
    • pop():移除栈顶的元素,同时返回被移除的元素。
    • peek():返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回它)。
    • isEmpty():如果栈里没有任何元素就返回true,否则返回false
    • clear():移除栈里的所有元素。
    • size():返回栈里的元素个数。这个方法和数组的length属性很类似。
class Stack:
    def __init__(self, size):
        self.size = size
        self.stack = []
        self.top = -1

    def is_empty(self): #isEmpty():如果栈里没有任何元素就返回`true`,否则返回`false`。
        return self.top == -1

    def is_full(self):
        return self.top == self.size - 1

    # push(element):  添加一个新元素到栈顶位置.
    def push(self, item):
        if not self.is_full():
            self.stack.append(item)
            self.top += 1
        else:
            print("栈已满")
    #pop():移除栈顶的元素,同时返回被移除的元素。
    def pop(self):
        if not self.is_empty():
            item = self.stack.pop()
            self.top -= 1
            return item
        else:
            print("栈为空")


    # peek():返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回它)。
    def peek(self):
        if not self.is_empty():
            return self.stack[self.top]
        else:
            print("栈为空")

六.队列

队列(Queue)是一种数据结构,遵循先进先出(FIFO,First In First Out)的原则。这意味着最先放入队列的元素最先被取出。队列的基本操作包括入队(Enqueue)、出队(Dequeue)、查看队头元素(Front或Peek)和检查队列是否为空(IsEmpty)。

队列的基本操作

  1. 入队(Enqueue):将一个元素添加到队尾。
  2. 出队(Dequeue):从队头移除一个元素并返回这个元素。
  3. 查看队头元素(Front/Peek):返回队头元素,但不移除它。
  4. 检查队列空(IsEmpty):判断队列是否为空。

队列的特点

  • 顺序性:队列中的元素按特定的顺序排列。
  • 限制性:只能在队尾进行插入操作,而只能从队头进行删除操作。
  • 内存结构:可以采用数组或链表实现。

队列常见的操作

  • enqueue(element):向队列尾部添加一个(或多个)新的项。
  • dequeue():移除队列的第一(即排在队列最前面的)项,并返回被移除的元素。
  • front():返回当前队列中第一个元素,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息——与Stack类的peek方法非常类似)。
  • isEmpty():如果队列中不包含任何元素,返回true,否则返回false
  • size():返回队列包含的元素个数,与数组的length属性类似.

队列的实现

  1. 基于数组的实现

    • 使用固定大小的数组来存储队列元素。
    • 需要注意队满和队空情况,以避免溢出或下溢。
    • 还需要记录队头和队尾的位置。
    class Queue:
        def __init__(self, size):
            self.size = size
            self.queue = [None] * size
            self.front = self.rear = -1
    
        def is_empty(self):
            return self.front == -1
    
        def is_full(self):
            return (self.rear + 1) % self.size == self.front
    
        def enqueue(self, item):
            if not self.is_full():
                if self.is_empty():
                    self.front = self.rear = 0
                else:
                    self.rear = (self.rear + 1) % self.size
                self.queue[self.rear] = item
            else:
                print("队列已满")
    
        def dequeue(self):
            if not self.is_empty():
                item = self.queue[self.front]
                if self.front == self.rear:
                    self.front = self.rear = -1  # Queue is empty after dequeuing
                else:
                    self.front = (self.front + 1) % self.size
                return item
            else:
                print("队列为空")
    
        def peek(self):
            if not self.is_empty():
                return self.queue[self.front]
            else:
                print("队列为空")
    

七.链表

  • 链表(Linked List)是一种基本的数据结构,用于存储一系列的数据元素。与数组不同,链表中的元素不需要在内存中连续存储,而是通过指针(或引用)相互链接。链表的每个元素称为节点(Node),每个节点不仅存储数据,还存储一个或多个指向其他节点的指针。

链表的基本结构

一个链表通常由以下几个部分组成:

  1. 节点(Node)
  • 每个节点包含两个主要部分:
    • 数据域(Data):存储节点的数据。
    • 指针域(Pointer):指向下一个节点的指针(在单向链表中),或指向前后节点的指针(在双向链表中)。
  1. 头指针(Head)
  • 链表的起始节点的指针。如果链表为空,头指针通常为 None

链表的类型

  1. 单向链表(Singly Linked List):

    • 每个节点只包含一个指向下一个节点的指针。
    • 可以从头节点开始向后遍历,但不能反向遍历。
  2. 双向链表(Doubly Linked List):

    • 每个节点包含两个指针:一个指向下一个节点,一个指向前一个节点。
    • 支持从头到尾和从尾到头的双向遍历。
  3. 循环链表(Circular Linked List):

    • 最后一个节点的指针指向头节点,而不是 None,形成一个环。
    • 可以是单向或双向的循环链表。

链表的基本操作

  1. 插入操作

    • 在链表的头部、尾部或特定位置插入节点。
  2. 删除操作

    • 删除特定值的节点,或删除指定位置的节点。
  3. 查找操作

    • 根据值查找节点并返回其位置。
  4. 遍历操作

    • 从头部访问链表中的每个节点,通常用于打印链表中的元素。

链表的优缺点

优点

  • 动态大小:链表可以根据需要动态增长或缩小,适合需要频繁插入和删除的场景。
  • 不需要连续内存:在内存中可以散布存储,避免了数组需要预先分配固定大小的问题。

缺点

  • 随机访问性能差:由于元素不在连续内存中,访问特定位置的元素时需要线性查找,时间复杂度为 O(n)。
  • 额外的内存开销:每个节点都需要额外的内存来存储指针,尤其在存储大量数据时,开销比较明显。

链表常见的操作

  • append(element):向列表尾部添加一个新的项

  • insert(position, element):向列表的特定位置插入一个新的项。

  • remove(element):从列表中移除一项。

  • indexOf(element):返回元素在链表中的索引。如果列表中没有该元素则返回-1

  • removeAt(position):从列表的特定位置移除一项。

  • isEmpty():如果链表中不包含任何元素,返回true,如果链表长度大于0则返回false

  • size():返回链表包含的元素个数。与数组的length属性类似。

# 创建节点类,用于存放每个节点信息
class Node():
    def __init__(self, el):
        self.el = el
        self.next = None


# 创建链表类
class LinkedList():
    # 链表的类 初始化数据个数和头部节点
    def __init__(self):
        self.length = 0
        self.head = None

    # 根据元素获取链表中的位置
    def indexof(self, el):
        # 定义变量, 保存信息
        current = self.head
        index = 0
        # 找到元素所在的位置
        while (current != None):
            if (current.el == el):
                return index
            index += 1
            current = current.next
        return -1  # 来到这个位置, 说明没有找到, 则返回-1

    # 给链表尾部追加元素
    def append(self, el):
        # 根据传入的数据创建新节点
        newNode = Node(el)
        # 如果是空链表直接把头部节点指定为新节点
        if (self.head == None):
            self.head = newNode
        # 链表不为空
        else:
            # 定义变量,保存当前头部节点
            current = self.head
            # 循环找到链表中最后一个节点
            while (current.next != None):
                current = current.next
            # 把最后一个节点的next设置为新节点
            current.next = newNode
        self.length += 1  # 增加链表长度

    # 根据下标插入节点
    def insert(self, position, element):
        # 检测越界问题: 越界插入失败
        if (position < 0 or position > self.length):
            return False
        # 定义变量, 保存信息
        newNode = Node(element)
        current = self.head
        previous = None
        index = 0
        if (position == 0):
            newNode.next = current
            self.head = newNode
        else:
            while (index < position):
                previous = current
                current = current.next
                index += 1
            newNode.next = current
            previous.next = newNode
        self.length += 1
        return True

    def removeAt(self, position):
        # 检测越界问题: 越界移除失败, 返回None
        if (position < 0 or position >= self.length):
            return None
        # 定义变量, 保存信息
        current = self.head
        previous = None
        index = 0
        # 判断是否是移除第一项
        if (position == 0):
            self.head = current.next
        else:
            while (index < position):
                previous = current
                current = current.next
                index += 1
            previous.next = current.next
        self.length -= 1
        return current.el

    # 根据元素删除信息
    def remove(self, el):
        index = self.indexof(el)
        return self.removeAt(index)

    # 判断链表是否为空
    def isEmpty(self):
        return self.length == 0

    # 获取链表的长度
    def size(self):
        return self.length


list1 = LinkedList()
for i in range(6):
    list1.append(i)
print(list1.indexof("hello"))  # -1
print(list1.indexof(4))  # 4
print(list1.remove(4))  # 4
print(list1.size())  # 5
  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值