python 數據結構與算法學習筆記(一)線性結構

?1.順序表
?2.鏈表
?3.棧
?4.隊列

??線性結構是一種有序數據項的集合,其中每個數據項都有唯一的前驅和后繼(除第一個沒有前驅,最后一個沒有后繼)。不同線性結構的關鍵區別在于數據項增減的方式,有的結構只允許數據從一端添加,而有的結構則允許數據從兩端移除。不同的方式形成了不同的線性結構,如棧(Stack)、隊列(Queue)、雙端隊列(Deque)和列表(List)。

1. 順序表

??(1)連續存儲與順序表
??計算機內部存儲的本質是將是將所需要存儲的數據類型轉換為二進制表示,并存儲在基本存儲單元中(字節),1字節=8位,不同的數據類型所占用的內存大小不同,如32位計算機中,基本int占4個字節,char占1個字節。存儲在基本單元中的數據都是0、1,需要通過存儲時聲明的數據類型,確認在取出時是當作int或char處理。
??連續存儲的概念是,定義一個有順序的數據集合,如List = [2,54,13,31],在存儲時(假設一個數字占4個字節),將各個數字轉換為二進制數據,在創建List集合時,集合指向的內存地址為起始位置0x17,對于第0個元素則以0x17標記,由于一個數字占4個字節,那么下一個數字存儲的內存地址為0x17+41=0x21,此后依次類推(起始地址+下標數據類型所占字節數)。

??如上所述,在內存中以連續的存儲空間來存儲的數據集合,即為順序表。在順序表中,數據的取出,按照起始地址+下標數據類型所占字節數來索引。但這僅是順序表中數據類型一致時,如果順序表中數據類型不一致,由于不同數據類型所占內存大小不一,所以不能直接將其按順序存儲,因為這樣會導致無法推算某個下標對應的內存地址。所以在順序表做指向的內存中不直接存儲數據,而是存儲指向存儲數據的地址:

??
(2)順序表的結構與實現*
??順序表在實現時,除了數據存儲空間,一般還需要添加一個表頭來存儲順序表的信息(順序表內存多大、現在存儲了多少)。順序表實現的兩種基本方式是一體式結構(表頭和存儲空間連續)和分離式結構(表頭和存儲空間分離,表頭最后一個內存存儲了指向存儲空間的地址):
在實現過程中一般采用分離式結構,以免順序表在變換或擴充時,重新申請內存導致順序表指向表頭的地址變化。同時在擴充時一般采用兩種策略:①增加固定內存;②每次在前面的基礎上翻倍。
??(3)順序表的操作
??①增加元素:

??②刪除元素時間復雜度同上

2. 鏈表

?2.1 單鏈表

??很明顯,順序表存在一個問題,在進行擴充時,如果當前內存不足,需要重新申請內存,將原內存存儲遷移過去,這樣會同時造成時間(復制)和空間(再次申請內存時預留)的浪費。那么能否實現這樣一個表,保留順序表索引的特性,同時,在擴充時,動態的申請內存直接添加呢?
??(1)鏈表的結構
??鏈表就能夠實現這樣的功能,存儲一個元素的區域不再是一個元素的大小,還需要包含一個內存區域來存儲指向下一個元素的地址:


??(2)python中地址的指向
??在python中,創建一個變量a = 10,a并不像是C一樣是指存儲10的內存的別名,也無法像C一樣創建一個指針變量來指向一個地址。python中的變量名實際上保存的是指向保存10的內存的地址。所以在python中很方便的可以實現鏈表結構,通過直接創建一個變量即可作為指向一塊內存的地址。
??(3)鏈表的實現
??通過python實現List,鏈表結構如下:

??(4)單鏈表與順序表的對比
??①鏈表失去了順序表隨機讀取的優點,同時由于鏈表還需要存儲地址,空間開銷大,但存儲空間靈活;
??②在刪除和插入操作中,鏈表主要是遍歷耗時,刪除和插入都是O(1)的;而順序表遍歷查找很快,但拷貝覆蓋耗時。

單向鏈表代碼:

# coding:utf-8

class Node(object):

    def __init__(self,elem = None):
        self.elem = elem
        self.next = None

class SingleLinkList(object):
    """single Link list"""
    def __init__(self):
        self.__head = None

    def is_empty(self):
        """confirm whether the list is empty"""
        return self.__head == None

    def length(self):
        """the length of list"""
        cur = self.__head
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """travel the list,and print the every value of the list"""
        print("[",end=" ")
        cur = self.__head
        while cur != None:
            print(cur.elem,end = ", ")
            cur = cur.next

        print("]",end=" ")

    def add(self,elem):
        """add element into the head of list"""
        node = Node(elem)
        node.next = self.__head
        self.__head = node

    def append(self,elem):
        """add element into the tail of list"""
        node = Node(elem)
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next != None:
                cur = cur.next

            cur.next = node

    def insert(self,pos,elem):
        """insert element into the specific index position of list"""
        if pos <= 0:
            self.add(elem)
        elif pos > self.length() - 1:
            self.append(elem)
        else:
        
            node = Node(elem)
            pre = self.__head
            count = 0
            while count < pos - 1:
                count += 1
                pre = pre.next
            node.next = pre.next
            pre.next = node
            

    def remove(self,elem):
        """remove a element that is found first"""
        if self.is_empty():
            return "empty list"
        else:
            cur = self.__head
            pre = None
            while cur != None:
                if cur.elem == elem:
                    if cur == self.__head:
                        self.__head = cur.next
                        
                    else:
                        pre.next = cur.next
                        cur.next = None
                    return
                else:
                    pre = cur
                    cur = cur.next



    def search(self,elem):
        """confirm whether the element is exist"""
        if self.is_empty():
            return "empty list"
        else:
            cur = self.__head
            while cur != None:
                if cur.elem == elem:
                    return True
                else:
                    cur = cur.next
            return False


if __name__ == "__main__":
    ll = SingleLinkList()
    print("the list is empty:",ll.is_empty())
    print("the length of empty list:",ll.length())

    ll.append(1)
    print("the list is empty:",ll.is_empty())
    print("the length of  list:",ll.length())


    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)

    print("---1 2 3 4 5 6---------------------")
    print("---88 7 1 16 2 3 4 5 6---------------------")
    ll.add(7)
    ll.insert(-1,88)
    ll.insert(3,16)
    ll.travel()
    print()
    print("------------------------------")
    print(ll.search(3))
    ll.remove(16)
    ll.travel()
    print()
    ll.remove(88)
    ll.travel()
    print()
    ll.remove(6)
    ll.travel()

?2.2 單向循環鏈表

??單向循環鏈表與單鏈表結構上的唯一區別就是尾結點不再指向None,而是指向頭節點,形成一個閉環。
代碼實現:

# coding:utf-8

class Node(object):

    def __init__(self,elem = None):
        self.elem = elem
        self.next = None

class SingleLinkList(object):
    """single Link list"""
    def __init__(self,node = None):
        self.__head = node
        if node:
            node.next = node

    def is_empty(self):
        """confirm whether the list is empty"""
        return self.__head == None

    def length(self):
        """the length of list"""
        if self.is_empty():
            return 0
        cur = self.__head
        count = 1
        while cur.next != self.__head:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """travel the list,and print the every value of the list"""
        print("[",end=" ")
        if self.is_empty():
            print("",end = "")
        else:
            cur = self.__head
            while cur.next != self.__head:
                print(cur.elem,end = ", ")
                cur = cur.next
            print(cur.elem,end = " ")
        print("]",end = " ")

    def add(self,elem):
        """add element into the head of list"""
        node = Node(elem)
        if self.is_empty():
            self.__head = node
            node.next = node
        else:
            cur = self.__head
            while cur.next != self.__head:
                cur = cur.next
            node.next = self.__head
            self.__head = node
            cur.next = self.__head

    def append(self,elem):
        """add element into the tail of list"""
        node = Node(elem)
        if self.is_empty():
            self.__head = node
            node.next = self.__head
        else:
            cur = self.__head
            while cur.next != self.__head:
                cur = cur.next
            cur.next = node
            node.next = self.__head

    def insert(self,pos,elem):
        """insert element into the specific index position of list"""
        if pos <= 0:
            self.add(elem)
        elif pos > self.length() - 1:
            self.append(elem)
        else:
        
            node = Node(elem)
            pre = self.__head
            count = 0
            while count < pos - 1:
                count += 1
                pre = pre.next
            node.next = pre.next
            pre.next = node
            

    def remove(self,elem):
        """remove a element that is found first"""
        if self.is_empty():
            return "empty list"
        else:
            cur = self.__head
            pre = None
            while cur.next != self.__head:
                if cur.elem == elem:
                    #head node
                    if cur == self.__head:
                        tail = self.__head
                        while tail != self.__head:
                            tail = tail.next
                        self.__head = cur.next
                        tail.next = self.__head
                        
                    else:
                    #median node
                        pre.next = cur.next
                        cur.next = None
                    return
                else:
                    pre = cur
                    cur = cur.next
            #tail node
            if cur.elem == elem:
                if cur == self.__head:
                    self.__head = None
                else:
                    pre.next = self.__head
                    cur.next = None

    def search(self,elem):
        """confirm whether the element is exist"""
        if self.is_empty():
            return "empty list"
        else:
            cur = self.__head
            while cur.next != self.__head:
                if cur.elem == elem:
                    return True
                else:
                    cur = cur.next
            if cur.elem == elem:
                return True
            return False


if __name__ == "__main__":
    ll = SingleLinkList()
    print("the list is empty:",ll.is_empty())
    print("the length of empty list:",ll.length())

    ll.append(1)
    print("the list is empty:",ll.is_empty())
    print("the length of  list:",ll.length())


    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)

    print("---1 2 3 4 5 6---------------------")
    print("---88 7 1 16 2 3 4 5 6---------------------")
    ll.add(7)
    ll.insert(-1,88)
    ll.insert(3,16)
    ll.travel()
    print()
    print("------------------------------")
    print(ll.search(3))
    ll.remove(16)
    ll.travel()
    print()
    ll.remove(88)
    ll.travel()
    print()
    ll.remove(6)
    ll.travel()

?2.3 雙向鏈表

??雙向鏈表的節點,除頭節點和尾節點,每個節點都會指向前驅節點和后繼節點:

代碼實現

# coding:utf-8

class Node(object):

    def __init__(self,elem = None):
        self.elem = elem
        self.next = None
        self.prev = None

class DoubleLinkList(object):
    """single Link list"""
    def __init__(self):
        self.__head = None

    def is_empty(self):
        """confirm whether the list is empty"""
        return self.__head == None

    def length(self):
        """the length of list"""
        cur = self.__head
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """travel the list,and print the every value of the list"""
        print("[",end=" ")
        cur = self.__head
        while cur != None:
            print(cur.elem,end = ", ")
            cur = cur.next

        print("]",end=" ")

    def add(self,elem):
        """add element into the head of list"""
        node = Node(elem)
        node.next = self.__head
        self.__head.prev = node
        self.__head = node


    def append(self,elem):
        """add element into the tail of list"""
        node = Node(elem)
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next != None:
                cur = cur.next

            cur.next = node
            node.prev = cur

    def insert(self,pos,elem):
        """insert element into the specific index position of list"""
        if pos <= 0:
            self.add(elem)
        elif pos > self.length() - 1:
            self.append(elem)
        else:
        
            node = Node(elem)
            cur = self.__head
            count = 0
            while count < pos:
                count += 1
                cur = cur.next
            node.next = cur
            node.prev = cur.prev
            cur.prev.next = node
            cur.prev = node

    def remove(self,elem):
        """remove a element that is found first"""
        if self.is_empty():
            return "empty list"
        else:
            cur = self.__head
            while cur != None:
                if cur.elem == elem:
                    if cur == self.__head:
                        self.__head = cur.next
                        if cur.next:
                            cur.next.prev = None
                            cur.next = None
                    else:
                        if cur.next is None:
                            cur.prev.next = None
                            cur.prev = None
                        else:
                            cur.prev.next = cur.next
                            cur.next.prev = cur.prev
                            cur.next = None
                            cur.prev = None
                    return
                else:
                    cur = cur.next



    def search(self,elem):
        """confirm whether the element is exist"""
        if self.is_empty():
            return "empty list"
        else:
            cur = self.__head
            while cur != None:
                if cur.elem == elem:
                    return True
                else:
                    cur = cur.next
            return False


if __name__ == "__main__":
    ll = DoubleLinkList()
    print("the list is empty:",ll.is_empty())
    print("the length of empty list:",ll.length())

    ll.append(1)
    print("the list is empty:",ll.is_empty())
    print("the length of  list:",ll.length())


    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)

    print("---1 2 3 4 5 6---------------------")
    print("---88 7 1 16 2 3 4 5 6---------------------")
    ll.add(7)
    ll.insert(-1,88)
    ll.insert(3,16)
    ll.travel()
    print()
    print("------------------------------")
    print(ll.search(3))
    ll.remove(16)
    ll.travel()
    print()
    ll.remove(88)
    ll.travel()
    print()
    ll.remove(6)
    ll.travel()

2. 棧

??棧(Stack)是一種有序的數據項集合,在棧中,數據項的加入和移除都發生在同一端(操作端叫棧頂)。距離棧底越近的數據,停留在棧中的時間越長,新加入的數據則會被最先移除,即后進先出。棧相當于對鏈表(順序表)進行了限制,不能任意刪除、插入,而只能在一端刪除添加。
??通過python內置List實現棧功能:

# coding:utf-8

class My_stack(object):
    def __init__(self):
        self.__list = []
        
    def push(self,item):
        self.__list.append(item)

    def pop(self):
        return self.__list.pop()

    def peek(self):
        if self.__list:
            return self.__list[-1]
        else:
            return None

    def is_empty(self):
        return self.__list == []

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


if __name__ == "__main__":
    s = My_stack()
    print(s.is_empty())
    s.push(1)
    s.push(2)
    s.push(3)
    s.push(4)
    s.push(5)
    s.push(6)
    print(s.size())
    print(s.peek())
    print(s.pop())
    print(s.size())

(1)棧的應用:簡單括號匹配
??在數值計算或者代碼中括號({])都是成對出現的,且嵌套出現,如如果出現非成對或非嵌套形式將會導致出錯,如()())(([)])都是錯誤的括號匹配方式。那么如何實現括號的正確匹配呢?算法的流程是,從左往右掃描,遇到左括號就壓入棧,遇到右括號則判斷棧是否為空,不為空則移除棧頂數據,為空則匹配失敗。當掃描完成后,判斷棧空,棧空則匹配成功,棧不空則匹配失敗。

# coding:utf-8

import sys
sys.path.append('./')
import my_stack as Stack

def par_checker(symbol_str):
    s = Stack.My_stack()
    balanced = True
    index = 0

    while index < len(symbol_str) and balanced:
        symbol = symbol_str[index]
        if symbol in "([{":
            s.push(symbol)
        elif symbol in ")]}" :
            if s.is_empty():
                balanced = False
            else:
                temp = s.peek()
                if matches(temp,symbol):
                    s.pop()
                else:
                    balanced = False

        index += 1

    if balanced and s.is_empty():
        return True
    else:
        return False

def matches(open_s,close_s):
    opens = list("([{")
    closes = list(")]}")
    return opens.index(open_s) == closes.index(close_s)


if __name__ == "__main__":
    print(par_checker('(([({})]))'))
    print(par_checker('((([)]))'))
    print(par_checker('(5+3)*2+(2-(3+1))'))

(2)棧的應用:十進制轉化為二進制
??進制之間的轉換就是將數字除以目標進制數,循環求余數,所有余數排列即為轉化后的數字,先求出的余數在低位排列,類似棧的先進后出,所以通過棧來實現:

# coding:utf-8

import sys
sys.path.append('./')

import my_stack as Stack

def divide_by2(d_num):
    remstack = Stack.My_stack()

    while d_num > 0:
        rem = d_num % 2
        remstack.push(rem)
        d_num = d_num // 2

    binary_str = ""

    while not remstack.is_empty():
        binary_str = binary_str + str(remstack.pop())
    
    return binary_str

if __name__ == "__main__":
    print(divide_by2(42))

(3)棧的應用:表達式轉換
??通常我們看到的計算表達式是中綴表示法,中綴表示法對于人來說比較好理解,但是如果不加括號、算符優先級問題,極其容易引起混淆。但對于計算機而言,最好是能明確規定所有計算順序,而不用處理優先級問題。
??所以,引入了前綴后綴表示法,這兩種方法只有一個規則:操作符只與其最近的兩個操作數進行計算(前綴為符號及其鄰近后兩位操作數,后綴為前兩位)。這兩種方法不用考慮優先級問題。實現中綴表達式轉化為前綴(后綴)表達式算法:
??①首先將中綴表達式轉換為全括號形式(如5+2*3+4(5+(2*3)+4)
??②按照下述方法移動操作符,并去除括號


轉換為后綴表達式:
①創建一個棧來存儲符號,從左向右讀取每個字符(數字、字母、符號、括號)
②如果讀取到字母或數字,直接追加到輸出列表中
③如果讀取到左括號,壓入棧中
④如果讀取到右括號:讀取棧頂符號,如果不是左括號,就一直彈出棧中元素,直到棧頂為左括號
⑤如果是操作符:判斷棧不為空時,棧頂操作符優先級是否大于等于當前讀取到符號,如果大于等于,循環彈出棧頂優先級高的操作符;再將當前符號壓入棧
⑥最后判斷棧是否為空,不空則依次彈出棧,追加至輸出列表

# coding:utf-8

import sys
sys.path.append('./')

import my_stack as Stack

def infix2postfix(infixexpr):
    #define priorities
    prec = {}
    prec["*"] = 3
    prec["/"] = 3
    prec["+"] = 2
    prec["-"] = 2
    prec["("] = 1

    op_stack = Stack.My_stack()
    postfix_list = []
    token_list = infixexpr.split()

    # travel expression
    for token in token_list:
        if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
            postfix_list.append(token)
        elif token == "(":
            op_stack.push(token)
        elif token == ")":
            top_token = op_stack.pop()
            while top_token != "(":
                postfix_list.append(top_token)
                top_token = op_stack.pop()
        else:
            while (not op_stack.is_empty()) and (prec[op_stack.peek()] >= prec[token]):
                postfix_list.append(op_stack.pop())
            op_stack.push(token)

    while not op_stack.is_empty():
        postfix_list.append(op_stack.pop())

    return "".join(postfix_list)

if __name__ == "__main__":
    s = "( ( ( A + 3 ) * B ) + ( 6 / C ) )"
    ss = "A + 3 * C + 6 / C"
    print(s)
    print(ss)
    print("---------")

    print(infix2postfix(s))
    print(infix2postfix(ss))

(4)棧的應用:后綴表達式求值
??算法:從左向右掃描,如果是數字則壓入棧,遇到符號則取出兩個數字進行運算(先取出來的數字在算符右邊),運算結果壓回棧。

# coding:utf-8

import sys
sys.path.append("./")

import my_stack as Stack

def post_eval(postfix_expr):
    op_num_stack = Stack.My_stack()
    token_list = postfix_expr.split()

    for token in token_list:
        
        if token not in "*/+-":
            token = int(token)
            op_num_stack.push(token)
        else:
            op2 = op_num_stack.pop()
            op1 = op_num_stack.pop()
            result = math_op(token,op1,op2)
            op_num_stack.push(result)
    return op_num_stack.pop()
            

def math_op(op,op1,op2):
    if op == "*":
        return op1 * op2
    elif op == "/":
        return op1 / op2
    elif op == "+":
        return op1 + op2
    elif op == "-":
        return op1 - op2

if __name__ == "__main__":
    ops = "32 4 + 6 * 7 8 / +"
    print(post_eval(ops))
    print("---------")
    print("(((32+4)*6)+(7/8) = ",(((32+4)*6)+(7/8)))

3. 隊列

??隊列(Queue)也是一種線性表,但只允許在一段插入,另一端進行刪除的操作,即先進先出
(1)隊列實現

# coding:utf-8

class Queue(object):
    def __init__(self):
        self.__list = []

    def enqueue(self,item):
        self.__list.append(item)

    def dequeue(self):
        return self.__list.pop(0)

    def is_empty(self):
        return self.__list == []

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

if __name__ == "__main__":
    q = Queue()
    print(q.is_empty())
    print(q.size())
    q.enqueue(1)
    q.enqueue(2)
    q.enqueue(3)
    q.enqueue(4)
    q.enqueue(10)
    print(q.dequeue())
    print(q.size())

(2)雙端隊列實現
??雙端隊列即允許兩端插入和取出

# coding:utf-8

class Deque(object):
    def __init__(self):
        self.__list = []

    def add_head(self,item):
        self.__list.insert(0,item)

    def add_tail(self,item):
        self.__list.append(item)

    def remove_head(self):
        return self.__list.pop(0)

    def remove_tail(self):
        return self.__list.pop()

    def is_empty(self):
        return self.__list == []

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

if __name__ == "__main__":
    d = Deque()
    print(d.is_empty())
    print(d.size())
    d.add_head(1)
    d.add_tail(2)
    d.add_head(3)
    d.add_head(4)
    d.add_tail(5)
    d.add_tail(6)
    print(d.remove_head())
    print(d.size())
    print(d.remove_tail())
    print(d.size())

(3)隊列的應用:熱土豆
??熱土豆問題也叫約瑟夫問題:傳燙手的熱土豆,鼓聲停止時,手里有土豆的人出列;如果去掉鼓,改為傳過固定人數,就出列,即約瑟夫問題。也就是一圈人,某個人開始數數,假設數到7的人出列。通過隊列的可以實現這樣的功能,每次從隊首取出一個人,并計數,沒有計數為7的人從隊尾入隊列,計數為7則不入隊列,一直循環,直到只剩下一個人。

# coding:utf-8

import sys
sys.path.append('./')

import Queue

def hot_patato(namelist,num):
    name_queue = Queue.Queue()
    for name in namelist:
        name_queue.enqueue(name)

    while name_queue.size() > 1:
        for i in range(num):
            name_queue.enqueue(name_queue.dequeue())
        name_queue.dequeue()

    return name_queue.dequeue()

if __name__ == "__main__":
    ll = ["A","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S"]
    print(hot_patato(ll,7))

(4)隊列的應用:打印任務
??當多人共享一臺打印機時,采取先到先服務的隊列策略來執行打印任務。在這種設定下,首要的問題是:打印作業系統的容量有多大?在能夠接受的等待時間內,系統能容納多少用戶以多高頻率提交多少打印任務?
??問題背景設置:


??對問題進行抽象:
①打印機屬性:
??i、私有字段:打印速度、當前是否有打印任務、當前任務所需剩余時間
??ii、打印機功能(方法):執行打印1秒、打印機是否空閑、是否開始下個任務
②打印任務屬性:
??i、私有字段:生成打印任務的時間、打印任務頁數
??ii、任務方法:獲取生成時間、獲取打印頁數、計算生成時間至開始打印本任務的等待時間
③打印流程模擬(設置打印時間范圍和打印速度):
??i、初始化打印機、打印隊列、等待時間表
??ii、在打印時間內,每1秒需要執行:
????a、是否生成了打印任務,如果生成了,加入打印隊列
????b、打印機是否忙且隊列是否為空,若打印機空閑且隊列不空,則開始打印下一任務,同時計算這個任務在開始打印時間與生成這個任務時的時間差
????c、執行1秒打印
注:
?①打印任務的生成:一共10人,每小時每次提交2次任務,則每一秒提交任務的概率為20/3600=1/180;
?②打印任務頁數隨機1-20,所以每次生成任務時,隨機生成頁數。

# coding:utf-8

import sys
sys.path.append('./')

import random
import Queue

class Printer:
    def __init__(self,ppm):
        self.__pagerate = ppm #print speed
        self.__current_task = None
        self.__time_remaining = 0

    def tick(self):
        if self.__current_task != None:
            self.__time_remaining = self.__time_remaining - 1
            if self.__time_remaining <= 0:
                self.__current_task = None

    def busy(self):
        if self.__current_task != None:
            return True
        else:
            return False

    def start_next(self,new_task):
        self.__current_task = new_task
        self.__time_remaining = new_task.get_pages() * 60 / self.__pagerate

class Task:
    def __init__(self,time):
        self.__timestamp = time
        self.__pages = random.randrange(1,21)

    def get_stamp(self):
        return self.__time_stamp

    def get_pages(self):
        return self.__pages

    def wait_time(self,current_time):
        return current_time - self.__timestamp

def new_print_task():
    num = random.randrange(1,181)
    if num == 111:
        return True
    else:
        return False

def simulation_print(num_seconds,pages_per_minute):
    lab_printer = Printer(pages_per_minute)
    print_queue = Queue.Queue()
    waiting_times = []

    for current_time in range(num_seconds):

        if new_print_task():
            task = Task(current_time)
            print_queue.enqueue(task)

        if (not lab_printer.busy()) and (not print_queue.is_empty()):
            next_task = print_queue.dequeue()
            waiting_times.append(next_task.wait_time(current_time))
            lab_printer.start_next(next_task)

        lab_printer.tick()

    ave_waiting_time = sum(waiting_times)/len(waiting_times)
    print("Print task within %d hours,averge wait %6.2f secs,%3d tasks remaining"\
            %(num_seconds/3600,ave_waiting_time,print_queue.size()))

if __name__ == "__main__":
    print("ppm 10:")
    for i in range(10):
        simulation_print(3600,10)
    print("ppm 5:")
    for i in range(10):
        simulation_print(3600,5)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,250評論 6 530
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,923評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,041評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,475評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,253評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,801評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,882評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,023評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,530評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,494評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,639評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,177評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,890評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,289評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,552評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,242評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,626評論 2 370

推薦閱讀更多精彩內容