数据结构(列表,队列,栈,链表)
1.说明
1.1 概念
简单来说,数据结构是用来设计数据以何种方式组织并存储在计算机中,像我们常见的列表,字典,元祖等都属于数据结构
1.2 分类
按照其逻辑可以分为线性结构,树结构,图结构
线性结构:数据结构中的元素存在一对一的相互关系,如列表
树结构:数据结构中的元素存在一对多的相互关系
图结构:数据结构中的元素存在多对多的相互关系
2.关于列表(数组)
在其他语言中列表被称为数组(像c),在Python中被称为列表,这两者之间还是存在区别的:
列表可以可以混合存储元素类型,像字符串,整数等,而数组不行,要求元素类型一致
数组长度是固定的,而Python中长度不够会开辟新的内存地址,再把原来的内容拷过来
3.关于队列(queue)
它属于一种数据集合,仅允许在列表的一端进行插入,另外一端进行删除
特点:联想我们排队打饭,都是先进先出,对头出队,队尾进队
双向队列:队列的两端都支持进队和出队操作
3.1 python队列内置模块
基本操作:
创建队列:queue = deque(li)
进队:append
出队:popleft
双向队列队首进队:appendleft
双向队列队尾进队:pop
from collections import deque lis = [9,5,2,7] q = deque(lis,8) # 最大长度是8 q.append(4) # 从队尾追加 q.popleft() # 队首出队 # 对于双向对列 q.appendleft(99) # 队首进队 q.pop() # 队尾出队
4.关于栈(stack)
栈也是一个数据集合,只能在一端进行插入或删除操作的列表
特点:后进先出。联想一摞书,我们取书只能从上取,存入也只能从上面存
利用python代码实现一个栈
class Stack(object): # 初始化栈 def __init__(self): self.items = [] # 判断栈是否为空 def is_empty(self): return self.items == [] # 返回栈顶 def peek(self): return self.items[len(self.items) - 1] # 返回栈大小 def size(self): return len(self.items) # 压栈 def push(self, item): self.items.append(item) # 出栈 def pop(self): return self.items.pop()
4.1 python栈内置模块
栈的基本操作:
进栈(压栈):push
出栈:pop
取栈顶:gettop(查看栈顶元素,但不取走) li[-1]
博客参考链接
5.关于链表
属于一种动态数据结构,链表中每一个元素都是一个对象,每个对象称为一个节点,包含有数据域key和指向下一个节点的指针next。通过各个节点之间的相互连接,最终串联成一个链表
链表的基本元素:
节点:每个节点有两个部分,左边部分称为值域,用来存放用户数据;右边部分称为指针域,用来存放指向下一个元素的指针。
head:head节点永远指向第一个节点
tail: tail永远指向最后一个节点
None:链表中最后一个节点的指针域为None值
链表和数组的区别:
1.数组需要提前定义大小,数据小于定义长度会浪费空间,大于定义长度则无法插入。而链表是动态增删数据,可以随意增加
2.数组适用于获取元素的操作,直接get索引即可。链表对于获取元素需要从头一直寻找,但是适用与增删,直接修改节点的指向即可
3.数组从栈中分配空间,操作方便,但是自由度小,链表从堆中分配空间, 自由度大但申请管理比较麻烦
节点定义:
class Node: def __init__(self,data=None,next=None): self.data = data self.next = next # 保存下一个节点对象 def __repr__(self): return str(self.data)
定义链表:
# 定义节点 node1 = Node(1) node2 = Node(2) node3 = Node(3) # 将每个节点的关系表示出来 node1.next = node2 node2.next = node3
链表出数:
# 顺序出数 def printList(node): while node: print(node) node = node.next printList(node1) # 逆序出数 def printBackward(lists): if lists == None: return printBackward(lists.next) print(lists) printBackward(node1)
5.1 链表基本操作
链表翻转(面试常见问题)
class Node: def __init__(self, data=None, next=None): self.data = data self.next = next # 保存下一个节点对象 def __repr__(self): return str(self.data) # 时间消耗O(n),空间消耗O(1) def rever(head): if head == None or head.next == None: # 边界条件 return head cur = head # 链表头 tmp = None # 临时变量 newhead = None # 翻转链表表头 while cur: # 存在链表头 tmp = cur.next # tmp为链表头下一节点 cur.next = newhead # 此时cur.next为None newhead = cur # 把链表头赋值给翻转链表头 cur = tmp # 把下一节点赋值给链表头 return newhead if __name__ == '__main__': head = Node(1) a1 = Node(2) a2 = Node(3) a3 = Node(4) head.next = a1 a1.next = a2 a2.next = a3 p = rever(head) while p: print(p.data) p = p.next
最终打印结果4,3,2,1
链表翻转的四种方式:链接
单向链表的详细操作方式:链接
常见数据结构:参看链接