最近在看书籍:python版小灰的算法之旅

2.1 什么是数组

数组是有限个相同类型的变量所组成的有序集合,数组中的每一个变量叫做元素。数组就是最简单、最常用的数据结构。shangjiantou5

另一个特点:在内存中顺序存储,可以很好地实现逻辑上的顺序表。

⬆⬆⬆

在python语言中,并没有直接使用数组这个概念,而是使用列表和元组这两种集合,本质上都是对数组的封装。

python 下面定义结构体 python定义结构体数组_python 下面定义结构体


接下来介绍数组的基本操作:

python 下面定义结构体 python定义结构体数组_列表_02

#数组的插入删除操作
class MyArray:
    def __init__(self, capacity):
        self.array = [None] * capacity
        self.size = 0

    def insert(self, index, element):
        # 判断访问下标是否超出范围
        if index < 0 or index > self.size:
            raise Exception("超出数组实际元素范围!")
        # 从右向左循环,逐个元素向右挪一位。
        for i in range(self.size-1, index-1, -1):
            self.array[i+1] = self.array[i]
        # 腾出的位置放入新元素
        self.array[index] = element
        self.size += 1

    def insert_v2(self, index, element):
        # 判断访问下标是否超出范围
        if index < 0 or index > self.size:
            raise Exception("超出数组实际元素范围!")
        # 如果实际元素达到数组容量上线,数组扩容
        if self.size >= len(self.array):
            self.resize()
        # 从右向左循环,逐个元素向右挪一位。
        for i in range(self.size-1, index-1, -1):
            self.array[i+1] = self.array[i]
        # 腾出的位置放入新元素
        self.array[index] = element
        self.size += 1

    def resize(self):
        array_new = [None] * len(self.array) * 2
        # 从旧数组拷贝到新数组
        for i in range(self.size):
            array_new[i] = self.array[i]
        self.array = array_new

    def remove(self, index):
        # 判断访问下标是否超出范围
        if index < 0 or index >= self.size:
            raise Exception("超出数组实际元素范围!")
        # 从左到右,逐个元素向左挪动一位
        for i in range(index, self.size-1):
            self.array[i] = self.array[i+1]
        self.size -= 1

    def output(self):
        for i in range(self.size):
            print(self.array[i])


array = MyArray(4)
array.insert_v2(0, 10)
array.insert_v2(1, 11)
array.insert_v2(2, 12)
array.insert_v2(3, 13)
array.insert_v2(4, 14)
array.insert_v2(2, 15)
array.insert_v2(2, 16)
array.insert_v2(2, 17)
array.remove(0)
array.output()

2.2什么是链表

链表linked list是一种在物理上非连续、非顺序的数据结构,由若干节点node所组成。

特点:随机存储

单向链表:每一个节点包括两部分,一部分是存放数据的变量data,另外一部分是指向下一个节点的指针next。

双向链表:每一个节点除了拥有data和next指针,还拥有指向前置节点的prev指针。

python 下面定义结构体 python定义结构体数组_指针_03


实现链表的完整代码:

为了尾部插入方便,代码中额外增加了指向链表尾节点的指针last。

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


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

    def get(self, index):
        if index < 0 or index >= self.size:
            raise Exception("超出链表节点范围!")
        p = self.head
        for i in range(index):
            p = p.next
        return p

    def insert(self, data, index):
        if index < 0 or index > self.size:
            raise Exception("超出链表节点范围!")
        node = Node(data)
        if self.size == 0:
            # 空链表
            self.head = node
            self.last = node
        elif index == 0:
            # 插入头部
            node.next = self.head
            self.head = node
        elif self.size == index:
            # 插入尾部
            self.last.next = node
            self.last = node
        else:
            # 插入中间
            prev_node = self.get(index-1)
            node.next = prev_node.next
            prev_node.next = node
        self.size += 1

    def remove(self, index):
        if index < 0 or index >= self.size:
            raise Exception("超出链表节点范围!")
        # 暂存被删除的节点,用于返回
        if index == 0:
            # 删除头节点
            removed_node = self.head
            self.head = self.head.next
            if self.size == 1:
                self.last == Node
        elif index == self.size - 1:
            # 删除尾节点
            prev_node = self.get(index-1)
            removed_node = prev_node.next
            prev_node.next = None
            self.last = prev_node
        else:
            # 删除中间节点
            prev_node = self.get(index-1)
            next_node = prev_node.next.next
            removed_node = prev_node.next
            prev_node.next = next_node
        self.size -= 1
        return removed_node

    def output(self):
        p = self.head
        while p is not None:
            print(p.data)
            p = p.next


linkedList = LinkedList()
linkedList.insert(3, 0)
linkedList.insert(4, 0)
linkedList.insert(9, 2)
linkedList.insert(5, 3)
linkedList.insert(6, 1)
linkedList.remove(0)
linkedList.output()

数组和链表的区别,优缺点及适用场景

2.3栈和队列

python 下面定义结构体 python定义结构体数组_算法_04


栈和队列,两种都属于逻辑结构,都可以使用数组或者链表来物理实现。


python 下面定义结构体 python定义结构体数组_列表_05

队列

python 下面定义结构体 python定义结构体数组_python 下面定义结构体_06


队列实现:

class MyQueue:
    def __init__(self, capacity):
        self.list = [None] * capacity
        self.front = 0
        self.rear = 0

    def enqueue(self, element):
        if (self.rear+1) % len(self.list) == self.front:
            raise Exception("队列已满 !")
        self.list[self.rear] = element
        self.rear = (self.rear+1) % len(self.list)

    def dequeue(self):
        if self.rear == self.front:
            raise Exception("队列为空 !")
        dequeue_element = self.list[self.front]
        self.front = (self.front+1) % len(self.list)
        return dequeue_element

    def output(self):
        i = self.front
        while i != self.rear:
            print(self.list[i])
            i = (i+1) % len(self.list)


myQueue = MyQueue(6)
myQueue.enqueue(3)
myQueue.enqueue(5)
myQueue.enqueue(6)
myQueue.dequeue()
myQueue.dequeue()
myQueue.enqueue(2)
myQueue.enqueue(4)
myQueue.output()

2.4神奇的哈希表

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构

它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。

这个映射函数叫做散列函数,存放记录的数组叫做散列表。

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

python中的哈希函数并没有直接取模运算来使hash值转换为数组下标,而是利用了位运算的方式来优化性能。

哈希冲突
产生原因:

数组长度有限,当从hash值转为数组下标,难免会有不同key值通过哈希函数获得的下标是相同的。

解决办法:

1.开放寻址法(找到的位置已经被占用,则向后查找空闲位置;寻址方式可以有很多种)
2.链表法(新来的映射直接插入到新的链表当中)

昨天越来越多,明天越来越少。