Python数据结构

概述

  • 数据结构
    • 抽象数据类型(AbstractDataType)
  • 算法
    • 解决问题的方法,或者叫计算方法和步骤
    • 算法的五大特征
      • 输入数量大于等于0
      • 输出数量大于等于1
      • 有穷性
      • 确定性
      • 可行性
  • 程序 = 数据结构 + 算法
  • 算法衡量
    • 衡量算法应该剔除机器配置,运算数量等无关因素
    • 时间复杂度
    • 空间复杂度
  • 时间复杂度计量
    • 最优时间复杂度
    • 最坏时间复杂度
    • 平均时间复杂度
    • 关注最坏时间复杂度
  • 时间复杂度计量规则
    • 基本操作,只有常数项,时间复杂度为1
    • 顺序结构,时间复杂度按加法计算
    • 循环结构,按乘法计算
    • 分支结构,取最大值
    • 最终得到一个方程式,然后化简,即取方程的阶
    • 判断一个算法的效率,关注操作数量的最高次项,其余可忽略
    • 没特殊说明,我们所分析的算法时间复杂度指的是最坏的复杂度
# 百钱买百鸡问题:一百块钱买一百只鸡,公鸡5元/只,母鸡3元/只,小鸡1元/3只
# 两个函数的算法,时间复杂度是一样的(都为O(n³)),但是所需时间是不同的
import time

def cockOne():
    start_time = time.time()
    
    for m in range(0, 101):
        for n in range(0, 101):
            for k in range(0, 301):
                if m + n + k == 100 and 5*m + 3*n + k/3 == 100:
                    print("{0} - {1} - {2}".format(m, n, k))
    
    end_time = time.time()
    
    print("CostTimes:{0}".format(end_time - start_time))
    
    
def cockTwo():
    start_time = time.time()
    
    for m in range(0, 20):
        for n in range(0, 33):
            for k in range(0, 100):
                if m + n + k == 100 and 5*m + 3*n + k/3 == 100:
                    print("{0} - {1} - {2}".format(m, n, k))
    
    end_time = time.time()
    
    print("CostTimes:{0}".format(end_time - start_time))
    
    
def cockThree():
    start_time = time.time()
    
    for m in range(0, 20):
        for n in range(0, 33):
            k = 100 - m - n
            if m + n + k == 100 and 5*m + 3*n + k/3 == 100:
                print("{0} - {1} - {2}".format(m, n, k))
    
    end_time = time.time()
    
    print("CostTimes:{0}".format(end_time - start_time))
    
    
cockOne()
cockTwo()
cockThree()

顺序表和链表

顺序表

  • 简单顺序表
    • 数据类型一致
    • 物理上和逻辑上都按顺序存储
    • 类似于数组
    • 好处:
      • 访问起来很方便(通过下标索引)
    • 坏处:
      • 增加删除操作很复杂
  • 索引顺序表
    • 数据可以很不规则
    • 物理上不按顺序存储,逻辑上按顺序存储
    • 表里面的所有数据都是索引(可以理解为指针),用于指向数据表
    • 索引的格式规整
  • 扩容问题
    • 每次定量增长:节省空间,操作频繁
    • 每次按比例增长:较浪费空间,操作较不频繁
  • Python-List操作
    • 分离技术实现的动态表
    • 空表:8个位置
    • 插入满:扩大四倍
    • 如果超过50000个,每次扩大一倍

链表

  • 链表
    • 分类
      • 单链表
      • 双向链表
      • 循环链表
      • 双向循环链表
  • 链表相关操作
    • is_empty():判断链表是否为空
    • length():返回链表长度
    • travel():遍历
    • add(item):在头部添加一个节点
    • append(item):在尾部添加一个节点
    • insert(pos, item):在指定位置pos添加节点
    • remove(item):删除一个节点
    • search(item):查找某节点是否存在
  • 实现方式
    • 一体式(顺序表)
    • 分离式(链表)
  • 顺序表VS链表(长度为n,时间复杂度表示)
    • 访问元素:1 : n
    • 头部插入:n : 1
    • 尾部插入:1 : n
    • 中间插入:n : n

单向链表

  • 单位元素的定义
    • 一般定义为结构或类
    • 必须包含至少两个内容:数据和指针
class SingleNode(object):
    def __init__(self, item):
        self.item = item
        self.next = None
  • 遍历算法
    • 采取循环,一般用while
    • 只要下一个元素不为空就继续
  • 求长度算法
    • 在head中存储长度
    • 每次求长度遍历一次
  • 伪代码实现
class SingleLinkList(object):
    def __init__(self):
        self.__head = None
        
    def isEmpty(self):
        return self._head == None
    
    def length(self):
        cur = self._head
        count = 0
        
        while cur != None:
            count += 1
            cur = cur.next
        return count
    
    def travel(self):
        cur = self._head
        
        while cur:
            print(cur.item)
            cur = cur.next
        
        return None
    
    def addFirst(self, item):
        # 创建一个节点
        node = SingleNone(item)
        # 第一步指向
        node.next = self._head
        # 第二步指向
        self._head = node
        
    def append(self, item):
        node = SingleNode(item)
        
        if self.isEmpty:
            self._head = node
        else:
            cur = self._head
            while cur.next:
                cur = cur.next
            cur.next = node
         
    def insert(self, pos, item):
        if pos <= 0:
            self.addFirst(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            node = SingleNode(item)
            count = 0
            
            pre = self._head
            while count < (pos-1):
                count += 1
                pre = pre.next
                
            node.next = pre.next
            pre.next = node
            
    def remove(self, item):
        cur = self._head
        pre = None
        
        while cur != None:
            if cur.item == item:
                if not pre:
                    self._head = cur.next
                else:
                    pre.next = cur.next
                    
                break
            else:
                pre = cur
                cur = cur.next
                
    def search(self, item):
        cur = self._head
        while cur != None:
            if cur.item == item:
                return True
            cur = cur.next
        return False

单向链表

class DLinkList(object):
    def __init__(self):
        self._head = None
       
    def is_empty(self):
        return self.head == None
    
    def length(self):
# 汉诺塔问题
# 方法:
# 当n=1时,A->C
# 当n=2时,A->B,A->C,B->C
# 当n=3时,把A上的两个盘子通过C移动到B上,调用递归实现
# 把A剩下的一个盘子移动到C上,A->C
# 把B上两个盘子借助A,移动到C上,调用递归

# 当n=n时,把A上的N-1个盘子借助C移动到B上,调用递归实现
# 把A剩下的一个盘子移动到C上,A->C
# 把B上 N-1个盘子借助A,移动到C上,调用递归

def hanNuo(n, a, b, c):
    '''
    n:代表n个盘子
    a:代表开始塔
    b:代表b过渡塔
    c:代表c目标塔
    '''
    if n == 1:
        print(a, "->", c)
        return None
    '''if n == 2:
        print(a, "->", b)
        print(a, "->", c)
        print(b, "->", c)
        return None'''
    
    # 把N-1个盘子,从a塔借助于c塔,挪到b塔上
    hanNuo(n-1, a, c, b)
    # 把A剩下的一个盘子移动到C上,A->C
    print(a, "->", c)
    # 把n-1个盘子,从b塔借助a塔挪到c塔
    hanNuo(n-1, b, a, c)
        
a = "A"
b = "B"
c = "C"

n = 3
hanNuo(n, a, b, c)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值