第三章——基本数据结构

0. 目标

  • To understand the abstract data types **stack, queue, deque, and list **.
  • To be able to implement the ADT‘s stack, queue, and deque using Python lists.
  • To understand the performance of the implementations of basic linear data structures.
  • To understand prefix, infix, and postfix expression formats.
  • To use stacks to evaluate postfix expressions.
  • To use stacks to convert expressions from infix to postfix.
  • To use queues for basic timing simulations.
  • To be able to recognize problem properties where stacks, queues, and deques are appropriate data structures.
  • To be able to implement the abstract data type list as a linked list using the node and reference pattern.
  • To be able to compare the performance of our linked list implementation with Python’s list
    implementation.

1. 课程笔记

1.1 线性数据结构——stack 堆

  1. stack特点1:LIFO last-in-fist-out, 最近的在Top,最老的在Base (例如一堆书)。常见例子:浏览过的URL存储在stack的数据结构,点击Back button可以退回到上一个。
  2. stack的实现
  • stack( ): 空的stack
  • push (item): 加入一个新数据在stack top,无返回
  • pop ( ): 移除一个在stack top,返回item
  • peek( ): 返回top item,但对stack 没有修改
  • is_empty( ): 返回布尔值
  • size( ): stack的大小,返回一个整数。
class Stack():  #最右边是top
    def __init__(self):
        self.stack = []
    def is_empty(self):
        if self.stack == []:
            return True
        else:
            False
    def push(self, item):
        self.stack.append(item)
        return self.stack
    def pop(self):
        m =self.stack.pop()
        return m
    def peek(self):
        last_num = len(self.stack) - 1
        return self.stack[last_num]
    def size(self):
        num = len(self.stack)
        return num
from Stack_function import Stack  ##从相同工程下的Stack_function.py取出Stack class的定义
s = Stack()
print(s.is_empty())
print(s.push(4))
print(s.push(5))
print(s.push('dog'))
print(s.pop())
print(s.peek())
print(s.size())
  1. stack应用一:翻转字符串


    a20a5b41-53cd-4435-94c5-0030a377c06a.png
    def reverse(self):
        new_list = []
        i = len(self.stack) - 1
        while i >= 0:
            m = self.stack[i]
            new_list.append(m)
            i = i - 1
        return new_list
  1. stack 应用二:检查括号是否成对出现:将符号放入stack中
from Stack_function import Stack

def cheek_balance(list):
    mystack = Stack() # 初始化一个stack的空间
    index = 0
    num = len(list)
    while index < num and index >= 0:
        i = list[index] #从list中取出一个需要判断的符号
        if i == '(': #push进stack
            mystack.push(i)
        if i == ')' and mystack.is_empty():
            return 'sorry, it is not balance'
        if i == ')':
            mystack.pop()

        index = index + 1

    if mystack.is_empty() == True:
        return 'perfect'
    else:
        return 'sorry'
  1. stack 应用三:十进制转化成二进制:将余数放入stack中
from Stack_function import Stack

def dicimal_to_binary(k):
    mystack = Stack()
    new_string = ''
    if k == 1:    #排除0、1的二进制
        return 1
    if k == 0:
        return 0
    else:
        while k != 0:
            remainder = k % 2 # 余数
            mystack.push(remainder)
            k = k // 2  #除数
    while not mystack.is_empty():
        index = str(mystack.pop())
        new_string = new_string + index   #字符串可以通过加号连接
    return new_string

print(dicimal_to_binary(20))

1.2 线性结构——Queue 队列

  1. 特点: FIFO
  2. 实现queue的数据结构
class Queue():
    def __init__(self):
        self.queue = []
    def enqueue(self, item):
        self.queue.insert(0, item)
    def dequeue(self):
        return self.queue.pop()
    def  is_empty(self):
        if len(self.queue) == 0:
            return True
        else:
            return False
        #return self.queue == []
    def size(self):
        return len(self.queue)
    def print_queue(self):
        return self.queue
  1. queue的应用一:烫手的山芋(hot potato): 约瑟夫环问题
from queue_structure import Queue

def hot_potato(List, num):
    queue = Queue() # 初始化一个排队
    for i in List:
        queue.enqueue(i)
    print(queue.print_queue()) #放入queue,已将考虑了bill在最前面

    while queue.size() > 1: #最后只剩下一个人
        for k in range(num):  # k = 1,2,3,4,5,6,7
            name = queue.dequeue()
            queue.enqueue(name)
        queue.dequeue() #达到7次后删除第一个

    return queue.print_queue()

Namelist = ["Bill","David","Susan","Jane","Kent","Brad"]
print (hot_potato(Namelist, 7))
  1. queue的应用二:打印机任务建模

1.3 线性结构——Dequeue 双端队列

  1. 特点: 两端都可以插入和输入
  2. 实现dequeue
class Dequeue():
    def __init__(self):
        self.dequeue = []

    def add_front(self, item):
        self.dequeue.append(item)

    def add_back(self, item):
        self.dequeue.insert(0, item)

    def delete_front(self):
        return self.dequeue.pop()
    
    def delet_back(self):
        return self.dequeue.pop(0)
    
    def is_empty(self):
        if self.dequeue == []:
            return True
        else:
            return False

    def size(self):
        return len(self.dequeue)

    def print_dequeue(self):
        print(self.dequeue)
  1. 双端队列的应用:回文检测
    ① 一个数据结构(list), 不可能凭空变成另一种数据结构(dequeue),只能通过一个一个添加的方法,将数据录入dequeue
    ②下面的dequeue的数据结构,没有dequeue[0],因为没有定义
from dequeue_structure import Dequeue

def Palindrome_check(list):
    dequeue = Dequeue()
    n = len(list)
    for i in range(n):
        dequeue.add_back(list[i]) #倒叙输入到dequeue中
    dequeue.print_dequeue()

    while dequeue.size() > 1:
       if dequeue.delete_back() == dequeue.delete_front():
           continue
       else:
           return "False"
    return "True"

1.4 无序队列(节点存储的数字大小是随机的)——链表(liked list)

  1. 为什么要使用链表?
    list插入的时候耗时太长(需要向后移动)
  2. 存储特点:
    ① 节点:一个具体存放的数值&下一个节点的地址
    ② head = none,既是代表了每个节点next node
    ③ 先add的当作old list,将最近添加的node连接到old list
  3. 构造链表结构
class Node:
    def __init__(self, initdata):
        self.data = initdata
        self.next = None

    def get_data(self):
        return self.data

    def get_next(self): #type:Node
        return self.next

    def set_data(self, new_data):
        self.data = new_data

    def set_next_node(self, new_next):
        self.next = new_next
  1. 实现链表
class UnorderList:
    def __init__(self):
        self.head = None #!! the end of structure / the entrance point

    def is_empty(self):
        return self.head == None #查看是否有head之后有node连接

    def add(self, item):
        temp = Node(item) #初始化一个节点
        temp.set_next_node(self.head)  #连接上end, 或者old list node
        self.head = temp

    def print_link_list(self):
        current = self.head
        list = []
        while current != None:
            item = current.get_data()
            list.append(item)
            current = current.get_next()
        return list


    def size(self):
        current = self.head
        sum_node = 1
        while current.get_next() != None:
            sum_node = sum_node + 1
            current = current.get_next()
        return sum_node

    def search(self, item):
        current = self.head  # star at the head
        while current.get_next() != None:
            if current.get_data() == item:
                return "Find" , item
            else:
                current = current.get_next()
        return "Not find"

    def remove(self, item):
        current = self.head
        pro_node = None
        found = False
        while not found:
            if current.get_data() == item:
                found = True
            else:
                pro_node = current
                current = current.get_next()

        if pro_node == None: #第一个节点删除
            self.head = current.get_next()
        else: #其他节点或者最后一个节点
            pro_node.set_next_node(current.get_next())
    
mylist = UnorderList()
print(mylist.is_empty())
mylist.add(31)
mylist.add(30)
mylist.add(29)
print(mylist.size())
print(mylist.remove(30))
print(mylist.print_link_list())
True
3
None
[29, 31]
  1. 扩展其他的功能append, insert, index, and pop
## 在最后一个节点后面增加一个节点,记录消耗的时间

def append(self, item):
    #search最后一个点
    current = self.head  #current is <class '__main__.Node'>
    new_node = Node(item)
    while current.get_next() != None:
        current = current.get_next()
    else:
        current.set_next_node(Node)
        return None
import time
mylist = UnorderList()
mylist.add(31)
mylist.add(30)
mylist.add(29)
tic = time.time()
mylist.append(10)
toc = time.time()
print('time is'+ str(1000*(toc-tic))+ 'ms')
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-21-29193cbe3960> in <module>()
      5 mylist.add(29)
      6 tic = time.time()
----> 7 mylist.append(10)
      8 toc = time.time()
      9 print('time is'+ str(1000*(toc-tic))+ 'ms')


AttributeError: UnorderList instance has no attribute 'append'
def insert(self, item, position):
    # initialize a node
    new_node = Node(item)
    current = self.head
    print(current.get_data())
    pos = 0
    pro_node = None
    find = False
    while not find:
        if pos != position:
            pro_node = current
            current = current.get_next()
            pos += 1
        if position == 0:  # Can I improve it?
            self.head = new_node
            new_node.set_next_node(current)
            find = True
        else:
            pro_node.set_next_node(new_node)
            new_node.set_next_node(current.get_next())
            find = True
def index(self, num):
    current = self.head
    pos = 0
    Find = False
    while not Find:
        if current.get_data() == num:
            return pos
        else:
            current = current.get_next()
            pos += 1
def pop(self):
    current = self.head
    Find = False
    pro_node = None
    while not Find:
        if current.get_next() != None:
            pro_node = current
            current = current.get_next()
            print(pro_node.get_data())

        else:
            pro_node.set_next_node(None)
            Find = True
  1. 有序链表,例如从小到大排列
class OrderList():
    def __init__(self):
        self.head = None
    def add(self, item):
        node = Node(item)
        node.set_next_node(self.head)
        self.head = node
        
    def print_list(self):
        current = self.head
        list = []
        while current != None:
            item = current.get_data()
            list.append(item)
            current = current.get_next()
        return list
    
    def search(self, item):
        current = self.head
        while current != None:
            if current.get_data() == item:
                return 'Find it'
                
            if current.get_data() > item:
                return 'Sorry, you dont find it'
            else:
                print('serch:', current.get_data())
                current = current.get_next()
        return 'Dont find it'
    
    def add_new_node(self, item):
        current = self.head
        pro_node = None
        print(type(pro_node))
        Find = False
        new_node = Node(item)
        pos = 0
        while not Find :

            if current.get_data() >= item:
                if pos == 0:  # 在位置0加入
                    self.head = new_node
                    new_node.set_next_node(current)
                    Find = True
                
                else:  #在中间其他位置加入|
                    pro_node.set_next_node(new_node)
                    new_node.set_next_node(current)
                    Find = True
                
            else:
                pro_node = current
                print ('through:', current.get_data())
                current = current.get_next()
                pos += 1
            
            if current.get_next() == None: #最后一个节点加入
                current.set_next_node(new_node)
                Find = True     
                
order_list = OrderList()
order_list.add(11)
order_list.add(9)
order_list.add(6)
print('1:', order_list.print_list())
# search
print('2:', order_list.search(8))
#add
order_list.add_new_node(12)
print('3:',order_list.print_list())
('1:', [6, 9, 11])
('serch:', 6)
('2:', 'Sorry, you dont find it')
<type 'NoneType'>
('through:', 6)
('through:', 9)
('3:', [6, 9, 11, 12])
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • 1.梦想变卖者 2.yesbuter 3.安全感自缢者 4.依赖 自由 喜欢 与爱的本质区别 5.潜能利用者 6....
    奥黛丽黑喵阅读 198评论 0 0
  • 今天3.8国际妇女节,先祝各位女性和选择走向女性的同胞们节日快乐! 所有人最早接触的女人,应该都是自己的母亲了吧。...
    文哲chan阅读 208评论 0 0
  • 2018年到来的第一刻钟我给自己送了一份新年的礼物。它就是——刘润的《五分钟商学院》简称“五商”。它...
    小利说阅读 348评论 1 3
  • 第十四章 爱情的真谛无非就是“你懂我我懂你” (一) 像一个快乐的小鸟,连走路都觉得应该用蹦蹦跳跳来诠释自己的快...
    灯歆先生阅读 160评论 0 1
  • 说道饺子,做为陕西人的我打小就喜欢吃,现在儿子也喜欢,作为妈妈最开心就是南方出生的小子也喜欢吃饺子。看着他吃...
    思念ok阅读 344评论 0 1