6.数据结构

数据结构

1.时间复杂度

1.时间复杂度:大O表示 -- O(f(n))
	量化算法需要的操作或者执行步骤的数量。
2.基本操作执行次数的函数 T(n):
    如果T(n)=5n^2+27n+1005,随着 n 变大,n^2 这项变得越来越重要,我们可以忽略其他项,只关注5n^2,系数 5 也变得不重要。我们说,T(n) 具有的数量级为 f(n)=n^2,或者 O( n^2 )

3.常见的时间复杂度比较:
	O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n)  < O(n!) < O(n^n)

2.线性数据结构

一.线性数据结构

  - 我们从四个简单但重要的概念开始研究数据结构。栈,队列,deques(双向队列), 列表是一类数据的容器,它们数据元素之间的顺序由添加或删除的顺序决定。一旦一个数据元素被添加,它相对于前后元素一直保持该位置不变。诸如此类的数据结构被称为线性数据结构。

  - 线性数据结构有两端,有时被称为左右,某些情况被称为前后。你也可以称为顶部和底部,名字都不重要。将两个线性数据结构区分开的方法是添加和移除元素的方式,特别是添加和移除元素的位置。例如一些结构允许从一端添加元素,另一些允许从另一端移除元素。

栈 -- 先进后出,后进先出

​ 概念:栈(有时称为“后进先出栈”)是一个元素的有序集合,其中添加移除新元素总发生在同一端。这一端通常称为“顶部”。与顶部对应的端称为“底部”。栈的底部很重要,因为在栈中靠近底部的元素是存储时间最长的。最近添加的元素是最先会被移除的

python实现栈:

# 列表实现栈
class Stack():
    # 创建一个空栈
    def __init__(self):
        self.items = []
    # 进栈添加数据 -- 追加数据
    def push(self,item):
        self.items.append(item)
    # 出栈移除数据 -- 从列表最后移除数据
    def pop(self):
        return self.items.pop()
    # 判断栈是否为空
    def isEmpty(self):
        return self.items == []
    # 栈长度
    def length(self):
        return len(self.items)
    
# 测试:
stack = Stack() # 实例化一个栈
alist = [1,2,3,4]
for item in alist:
	stack.push(item)
for i in range(stack.length()):
	print(stack.pop()) # 4 3 2 1

队列 -- 先进先出

​ 概念:队列是项的有序结合,其中添加新项的一端称为队尾,移除项的一端称为队首。当一个元素从队尾进入队列时,一直向队首移动,直到它成为下一个需要移除的元素为止。最近添加的元素必须在队尾等待。集合中存活时间最长的元素在队首,这种排序成为 FIFO,先进先出,也被成为先到先得。

python实现队列:

# 特性:先进先出
# 入队列:从队尾部向头部添加
# 出队列:从头部出队列
class Queue():
    # 创建一个队列
	def __init__(self):
		self.items = []
    # 入队列
	def enqueue(self,item):
		self.items.insert(0,item)
    # 出队列
	def dequeue(self):
		return self.items.pop()
    # 判断队列是否为空
	def isEmpty(self):
		return self.items == []
    # 队列长度
	def length(self):
		return len(self.items)
    
# 测试:
queue = Queue() # 实例化一个队列
alist = [1,2,3,4]
for item in alist:
	queue.enqueue(item)
for i in range(queue.length()):
	print(queue.dequeue())

1.队列的应用案例-烫手的山芋

烫手山芋游戏介绍:

​ 6个孩子围城一个圈,排列顺序孩子们自己指定。第一个孩子手里有一个烫手的山芋,需要在计时器计时1秒后将山芋传递给下一个孩子,依次类推。规则是,在计时器每计时7秒时,手里有山芋的孩子退出游戏。该游戏直到剩下一个孩子时结束,最后剩下的孩子获胜。请使用队列实现该游戏策略,排在第几个位置最终会获胜?

分析: 循环报数,每到第6个人,剔除队列,直到只剩最后一人

python代码实现:

class Queue():
    def __init__(self):
        self.items = []
    # 进入队列
    def enqueue(self,item):
        self.items.insert(0,item)
    # 出队列
    def dequeue(self):
        return self.items.pop()
    # 判断是否为空
    def isEmpty(self):
        return self.items == []
    # 队列长度
    def length(self):
        return len(self.items)

# 实例化一个队列对象
queue = Queue()
# 孩子列表
kids = list(range(1,7))
print(kids)
# 添加到队列
for i in kids:
    queue.enqueue(i)
    
# 循环移除队列,直到剩最后一人
while queue.length() > 1:
    for i in range(6):
        # 队列循环
        item = queue.dequeue()
        queue.enqueue(item)
    # 移除第6个孩子
    queue.dequeue()

print('最后获胜者:',queue.dequeue())

2.两个队列实现一个栈的效果

# 队列 先进先出 --> 栈 后进先出
class Queue():
    def __init__(self):
        self.items = []
    # 进入队列
    def enqueue(self,item):
        self.items.insert(0,item)
    # 出队列
    def dequeue(self):
        return self.items.pop()
    # 判断是否为空
    def isEmpty(self):
        return self.items == []
    # 队列长度
    def length(self):
        return len(self.items)

# 实例化两个队列
q1 = Queue()
q2 = Queue()
lis = [1,2,3,4]
# 入队列
for i in lis:
    q1.enqueue(i)
    
# 循环终止条件
while q1.length() > 0:
    for i in range(q1.length()-1):
        item = q1.dequeue()
        q2.enqueue(item)
    print(q1.dequeue())
    # 队列交换
    q1,q2 = q2,q1

3.两个栈实现一个队列效果

# 栈 后进先出 --> 队列 先进先出
class Stack():
    def __init__(self):
        self.items = []
    # 进栈
    def push(self,item):
        self.items.append(item)
    # 出栈
    def pop(self):
        return self.items.pop()
    # 判断是否为空
    def isEmpty(self):
        return self.items == []
    # 栈长度
    def length(self):
        return len(self.items)

# 实例化两个栈对象
s1 = Stack()
s2 = Stack()
lis = [1,2,3,4]
# 添加栈
for i in lis:
    s1.push(i)

# 改变栈顺序 -- 后进先出
for i in range(s1.length()):
    item = s1.pop()
    s2.push(item)
    
# 循环遍历s2
for i in range(s2.length()):
    print(s2.pop())

双端队列

特性: 可以从任意端(队首,队尾)添加,也可以从任意端移除

python代码实现:

class Deque():
    # 创建一个空队列
    def __init__(self):
        self.items = []
    # 从前边入队列
    def add_front(self,item):
        self.items.insert(0,item)
    # 从后边入队列
    def add_rear(self,item):
        self.items.append(item)
    # 从前边移除队列
    def remove_front(self):
        return self.items.pop(0)
    # 从后边移除队列
    def remove_rear(self):
        return self.items.pop()
    # 判断队列是否为空
    def is_empty(self):
        return self.items == []
    # 队列长度
    def length(self):
        return len(self.items)

回文检索 -- 设计程序,检测一个字符串是否为回文

回文:回文是一个字符串,读取首尾相同的字符,例如,radar toot madam

# 回文检索
def jiance(str):
    # 实例化双端队列对象
    deque = Deque()
    # 添加队列
    for i in str:
        deque.add_rear(i)
    # 判断是否是回文
    is_huiwen = True

    while (deque.length() > 1) and is_huiwen:
        # 首字符
        front = deque.remove_front()
        # 尾字符
        rear = deque.remove_rear()
        # 判断首尾字符是否相等
        if front != rear:
            is_huiwen = False

    return is_huiwen

# 测试
str = 'radar'
print(jiance(str)) # True

3.链表

​ 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是每一个结点(数据存储单元)里存放下一个结点的信息(即地址)

单向链表

​ 单向链表也叫单链表,是表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接域指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

python代码实现:

# 封装节点
class Node():
    def __init__(self,item):
        self.item = item # 元素域
        self.next = None # 连接域

# 封装链表
class Link():
    # 1.链表的头
    def __init__(self):
        self._head = None
        
    # 2.判断链表是否为空
    def is_empty(self):
        return self._head is None
    
    # 3.链表长度
    def length(self):
        cur = self._head
        count = 0
        while cur:
            count += 1
            cur = cur.next
        return count
    
    # 4.向链表头部添加节点元素
    def add_front(self,item):
        node = Node(item)
        node.next = self._head
        self._head = node
        
    # 5.向链表尾部添加节点元素
    def add_rear(self,item):
        node = Node(item)
        cur = self._head
        # 判断是否为空链表
        if self.is_empty():
            node.next = self._head
            self._head = node
            return
        # 循环链表找到最后一个节点元素
        while cur:
            pre = cur
            cur = cur.next
        node.next = None
        pre.next = node
        
    # 6.遍历链表
    def trasersal(self):
        if self.is_empty():
            print('链表中没有数据')
            return  # 终止程序
        # 表头位置不要动,重新赋值
        cur = self._head
        while cur:
            print(cur.item)
            cur = cur.next
            
    # 7.查找节点元素是否存在
    def search(self,item):
        cur = self._head
        # 判断是否为空链表
        if cur is None:
            return False
        while cur:
            if cur.item == item:
                return True
            cur = cur.next
        return False

    # 8.指定位置添加元素
    def add_index(self,pos,item):
        node = Node(item)
        if pos > self.length():
            print('超出链表索引位置,不能添加')
            return # 终止程序
        if pos == 0: # 从头添加
            node.next = self._head
            self._head = node
        sum = 1 # 当前链表位置
        cur = self._head
        while cur:
            pre = cur
            cur = cur.next
            if pos == sum:
                pre.next = node
                node.next = cur
            sum += 1

    # 9.删除链表节点元素
    def remove(self,item):
        pre = None # cur前一个节点
        cur = self._head
        while cur:
            if cur.item == item:
                if pre is None: # 删除的是第一个节点元素
                    self._head = cur.next
                    return # 终止程序
                pre.next = cur.next # 删除非第一个节点元素
            pre = cur
            cur = cur.next
        print('链表中没有你要删除的元素')
        
    # 10.反转链表
    def reverse(self):
        if self.is_empty():
            print('链表中没有数据,不能反转')
            return
        pre = None # 前一个节点
        cur = self._head # 当前节点
        nex = cur.next # 后一个节点
        while cur:
            cur.next = pre # 当前节点的下一个节点是前一个节点
            pre = cur
            cur = nex
            if cur is not None:
                nex = nex.next
        self._head = pre # 最后,把链表头放到链表最后一个节点

# 测试
# 实例化链表对象
link = Link()

print(link.is_empty())
link.trasersal()
link.add_front(1)
link.add_front(2)
link.add_rear(66)
print(link.search(2))
link.add_index(5,66)
link.remove(66)
link.reverse()
link.trasersal()

print(link.length())


原文地址:https://www.cnblogs.com/jia-shu/p/14716058.html