Python算法笔记(2)-初识数据结构-数组、链表、栈、队列、哈希表

在这里插入图片描述

1.数组

什么是数组

数组是一种数据结构,用来存储多个相同类型的数据,数组中元素是有序,通过下标来进行访问,数组元素中具有相同数据类型,可以由不同的下标和统一数组名来确定数组的唯一元素。

数组怎么用

一般数组形式为:dataType arrayName[length];
其中datatype是数据类型比如,int、float这些数据类型

arrayname则是数组的名称

length是数组的长度

比如int abc[4]就是定义了一个数组名为abc,长度为4的整形数组

也可以给数组赋值例如abc[0] = 123,就是给abc中第一个元素赋值为123

也可以同时给数组内所有元素赋值int abc[2] = {0,1,2}

如果数组的元素个数少于数组长度会自动赋值和初始化。

1.读取数组

abc = [1,2,3,4,5]
读取元素

abc = [1,2,3,4]
print(abc[3])

更新元素


abc = [1,2,3,4]
abc[3] = 120
print(abc[3])

在这里插入图片描述

2.插入元素

尾部插入


abc = [1,2,3,4]
abc.append(150)
print(abc)


在这里插入图片描述

中间插入


abc = [1,2,3,4]
abc.insert(2,120)
print(abc)


在这里插入图片描述

超范围插入
当数组超过插入范围时,这时候如果继续往数组内插入元素,会出现数组越界,为了能让数组在超过范围内进行插入就叫做超范围插入,但在python中这样不会出现数组异常,因为python会将超范围的数组在尾部进行插入

当只有4个元素,向其中插入第五个元素
在这里插入图片描述
在这里插入图片描述
当只有4个元素,向其中第99插入第五个元素


abc= [1,2,3,4]
abc.insert(100,120)
print(abc)

在这里插入图片描述
删除元素


abc= [1,2,3,4]
abc.remove(4)
print(abc)


在这里插入图片描述

数组的优点和缺点

优点缺点
1.按照索引查询速度快,可以实现随机访问根据内容查找元素速度慢,需要遍历整个数组
2.能够储存大量数据,占用空间小数组大小无法改变,会造成空间浪费
3.可以根据索引快速遍历引用,可以用循环语句数组只能存储一种类型的数据,无法去适应各种类型数据的存储需求
4.数组定义简单,访问方便增加和删除元素效率低,需要移动很多数据

2.链表

什么是链表

链表是一种数据结构,它由一系列的结点组成,每个结点包含一个数据域和一个指针域。数据域存储数据元素,指针域存储下一个结点的地址。链表的优点是可以动态地增加或删除结点,不需要连续的内存空间。链表的缺点是访问数据时需要从头结点开始遍历,效率较低

链表怎么用

下面以这四种为内容,分别简要介绍

class mylist:
    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):#插入节点
        nodelist = mylist(data)
        if self.size ==0:
            # 空链
            self.head =nodelist
            self.last = nodelist
        elif index == 0:
            ## 插入头部节点
            nodelist.next = self.head
            self.head = nodelist.next
    def remove(self,index):#删除节点
        if index == 0:
            #删除头节点
            remove_node = self.head
            self.head = self.head.next
            if self.size == 1:
                self.last == mylist
        elif index == self.size -1:
            #删除尾节点
            re_node = self.get(index-1)
            remove_node = re_node.next
            re_node.next = None
            self.last = re_node
        else:
        #删除中间节点
            re_node = self.get(index-1)
            ne_node = re_node.next.next
            remove_node = re_node.next
            re_node.next = ne_node
        self.size -=1
        return remove_node
    def find(self,data):#查找节点
        node = self.head
        while node:
            if node.data ==data:
                return node
            else:
                node = node.next
        return None
    def append(self, data):#添加一下新节点
        new_nodelist = mylist(data)
        if self.head is None:
            self.head = new_nodelist
        else:
            bte = self.head
            while bte.next:
                bte = bte.next
            bte.next = new_nodelist

    def out(self):
        p = self.head
        while p is not None:
            print(p.data)
            p = p.next
linklist = LinkedList()
linklist.insert(100,0)
linklist.insert(2,1)
linklist.insert(3,2)
linklist.append(5)
linklist.remove(0)
linklist.out()
te=linklist.find(5)
print(te.data)

链表和数组对比

数组的优势在于快速定位元素,对于读操作多和写操作少的场景适合

链表能够灵活插入和删除,对于频繁插入和删除的用链表更好

3.栈和队列

什么是物理结构和逻辑结构

逻辑结构:数据与数据直接的关系,常见的有:集合结构、线性结构、树形结构、图形结构
在这里插入图片描述
物理结构:一种是顺序存储结构、一种是链式存储结构

在这里插入图片描述

在这里插入图片描述

什么是栈

栈是一种线性结构,里面的元素只能先入后出最早进入的元素在栈底,最后进入的元素在栈顶

栈怎么用

入栈

入栈就是把新的元素放入栈中,新的元素称为栈顶

出栈

出栈就是把元素从栈中退出来,出栈的元素的前一个元素成为栈顶

什么是队列

队列是一种线性的数据结构,队列中的元素只能先进先出,队列的出口端叫做队头,入口端叫做队尾。

队列的基本操作

入队

入队就是把新元素放入队列中,只允许在队尾的位置放入元素,新元素的下一个位置就会成为新的队尾

出队

出队就是把元素移除队列,只允许队头的一侧移出元素,出队的元素最后一个元素就会成为新的队头。

栈和队列的使用方法

#使用collection.deque实现队列
from collections import deque
queue = deque() #创建一个空队列
#往队列里面添加元素
queue.append("1")
queue.append("2")
queue.append("3")
print(len(queue))#打印队列长度
print(queue)

#队列中移除元素
element = queue.popleft()
print(element)
print(queue)



在这里插入图片描述

4.哈希表

什么是哈希

哈希表通过key和值的映射即可快速找到相应的数据。哈希表也叫散列表,是储存key-value的映射集合,对于某个key,哈希表可以在接近O(1)内进行读写操作,哈希表通过哈希函数实现key和数组下标的转换,通过开放寻址法dict和链表法来解决哈希冲突。

什么是哈希函数

哈希把表对应的集合叫做字典,假设目前有一个很大的数据集在[1,2,3]中,如果每个都要按照最大值去开辟空间,那么就会造成空间浪费,所以我们需要将元素和数据的索引建立一个映射关系,这就是哈希函数。

什么是哈希冲突

由于数据越来越多,不同的key和数组下标,通过哈希函数获得下标有可能是相同的,所以造成数组下标变成同样的值,这也叫做哈希冲突。哈希冲突的处理方法主要有开放寻址法和链表法。

哈希表的使用方法

#创建一个空的哈希表
hashtable =dict()
hashtable["name"]="zhangsan"
hashtable["age"]=29
hashtable["gender"]="male"
hashtable["company"]="txxt"
#打印哈希表长度和内容
print(len(hashtable))
print(hashtable)
#读取哈希表中对应键值对的值
value = hashtable["name"]
print(value)
#删除键值对
del hashtable["company"]
print(hashtable)

在这里插入图片描述

使用开放寻址法实现哈希表

#定义一个哈希表
class hashtable:
    def __init__(self):
        self.size = 5
        self.table = [None]*self.size

    #定义一个哈希函数将字符串转化为整数
    def hash_changed(self,key):
        return sum(ord(c)for c in key)% self.size
    #定义元素插入
    def insert(self, key, value):
        #计算哈希值
        hash_cal = self.hash_changed(key)
        if self.table[hash_cal] is None:#如果该位置为空则插入元素
            self.table[hash_cal]=(key,value)
        else:#反之出现哈希冲突
            i = 1
            while   True:
                #出现哈希冲突重新计算位置
                newhashcal = (hash_cal+i)%self.size
                #如果不再出现冲突,则插入元素
                if self.table[newhashcal] is None:
                    self.table[newhashcal] =(key,value)
                    break
                else:
                    i+=1
#创建一个哈希表对象
hash_table = hashtable()
# 向哈希表中插入元素
hash_table.insert("name", "zhangsan")
hash_table.insert("age", 29)
hash_table.insert("comany", "kkiu")
hash_table.insert("incom", "8000")
hash_table.insert("like", "play basketball")
# 打印哈希表的内容
print(hash_table.table)



在这里插入图片描述

在这里插入图片描述