算法导论 第十章 基本数据结构

def:动态集合,由数学集合定义所衍生出来的,由算法操作的能增大,缩小或发生其他变化,我们称这样的集合是动态的。动态集合一般有如下操作:



10.1 栈和队列

def:栈是一种动态集合,在其上执行DELETE操作被删除的是最近插入的元素,实现的是一种先进后出的策略,被称为POP;INSERT操作被称为PUSH。其有一top属性指向最近插入的元素,当top<0时,栈中不包含任何元素,称栈是空的,若试图对一个空栈执行弹出操作,则称栈下溢。

class STACK():  
    def __init__(self, n):  
        self.stack = [None for i in range(n)]
        self.top = -1

    def __getitem__(self, key):
        return self.stack[key]

    def __setitem__(self, key, value):
        self.stack[key] = value

def STACK_EMPTY(S):
    if S.top == -1:
        return True
    else:
        return False

def PUSH(S, x):
    S.top = S.top + 1
    S[S.top] = x

def POP(S):
    if STACK_EMPTY(S):
        raise("underflow")
    else:
        S.top = S.top - 1
        return S[S.top + 1]

def:队列是一种动态集合,在其上执行DELETE操作被删除的是在集合中存在最久的元素,实现的是一种先进先出的策略,被称为DEQUEUE;INSERT操作被称为ENQUEUE。其有head属性指向队头元素,tail属性指向队尾元素(下一个新元素的位置)并在最后的位置环绕,head=tail时队列为空。

class QUEUE():
    def __init__(self, n):
        self.queue = [None for i in range(n)]
        self.length = n
        self.head = 0
        self.tail = 0
    def __getitem__(self, key):
        return self.queue[key]

    def __setitem__(self, key, value):
        self.queue[key] = value

def ENQUEUE(Q, x):
    Q[Q.tail] = x
    if Q.tail == Q.length-1:
        Q.tail = 0
    else:
        Q.tail = Q.tail + 1

def DEQUEUE(Q):
    x = Q[Q.head]
    if Q.head == Q.length -1:
        Q.head = 0
    else:
        Q.head = Q.head + 1
    return x

10.2 链表

def:链表是这样一种数据结构,对象中包含指针,各个对象按线性顺序排列,其顺序由各个对象里的指针决定。

链表元素通常包括关键字key,和两个指针prev和next,分别指向前一个元素与后一个元素,当prev指针为空时其为第一个元素,next指针为空时其为最后一个元素。而链表的head属性为指向第一个元素的指针。

链表根据时间使用情况有多种形式:1.单连接的,链表各个元素中不保护prev指针,只依赖于next指针决定对象的线性顺序。2.已排序的,链表的线性顺序与链表元素中关键字的线性顺序一致。3.循环链表,表头的prev指针指向最后一个元素,最后一个元素的next指向表头元素。

链表主要包含以下操作:search,线性查找第一个出现的关键字为k的元素;insert在链表头插入元素x;delete,删除链表中的元素x

class LISTNODE():
    def __init__(self, key):
        self.key = key
        self.prev = None
        self.next = None

class LIST():
    def __init__(self):
        self.head = None

def LIST_SEARCH(L, k):
    """
    theta(n)
    """
    x = L.head
    while x != None and x.key != k:
        x = x.next
    return x

def LIST_INSERT(L, x):
    """
    theta(1)
    """
    x.next = L.head
    if L.head != None:
        L.head.prev = x
    L.head = x
    x.prev = None

def LIST_DELETE(L, x):
    """
    theta(1)
    """
    if x.prev != None:
        x.prev.next = x.next
    else:
        L.head = x.next

    if x.next != None:
        x.next.prev = x.prev

def:哨兵(sentinel)是一个哑对象,其作用是简化边界条件的处理。在链表中加入哨兵,将链表变为双向循环链表,位于第一个元素和最后一个元素之间,取代head的作用。使得代码变得简洁,基本不能降低数据结构相关操作的渐近时间界,但可以减低常数因子。

class LISTNODE():
    def __init__(self, key):
        self.key = key
        self.prev = None
        self.next = None

class DL_LIST():
    def __init__(self):
        self.nil = LISTNODE(None)
        self.nil.next = self.nil
        self.nil.prev = self.nil
        

def DL_LIST_SEARCH(L, k):
    x = L.nil.next
    while x != L.nil and x.key != k:
        x = x.next
    return x

def DL_LIST_INSERT(L, x):
    x.next = L.nil.next
    L.nil.next.prev = x
    L.nil.next = x
    x.prev = L.nil

def DL_LIST_DELETE(L, x):
    x.prev.next = x.next
    x.next.prev = x.prev


10.3 指针和对象的实现

在许多不存在对象只有数组的环境中,需要表达对象的概念可以通过数组来实现对象的表达。

对象的多数组表示:对于同构的一组对象,使用n个数组来表示其n个属性。通过访问不同数组的相同下标来访问下标所对应的同一个对象的不同属性。


对象的当数组表示:使用一个数组来保存不同对象的数据,对对象附加数据来保存下一个或上一个对象的下标,下标所指向的为对象的第一个属性的位置,其余属性通过偏移来访问。


对象的分配与释放:对象池的雏形,申请一大块内存用于保存对象,每次新加入的对象都从这块内存中分配,使用自由表作为垃圾收集器

class STACK():
    def __init__(self, n):
        self.next = [None for i in range(n)]
        self.key = [None for i in range(n)]
        self.prev = [None for i in range(n)]
        self.free = self.INIT(n)
        self.list = None

    def INIT(self, n):
        for i in range(n):
            if i != 9:
                self.next[i] = i + 1
            if i != 0:
                self.prev[i] = i - 1
        return 0
    
    def ALLOCATE_OBJECT(self):
        if self.free == None:
            raise("out of space")
        else:
            x = self.free
            self.free = self.next[x]
            return x
        
    def FREE_OBJECT(self, x):
        self.next[x] = self.free
        self.free = x

    def PUSH(self, value):
        x = self.ALLOCATE_OBJECT()
        self.key[x] = value
        self.prev[x] = None
        self.next[x] = self.list
    
        if self.list != None:
            self.prev[self.list] = x
        self.list = x

    def POP(self):
        if self.list == None:
            raise("underflow")
        v = self.key[self.list]
        x = self.next[self.list]
        self.FREE_OBJECT(self.list)
        self.list = x
        return v

    def PRINT(self):
        x = self.list
        print("list-----------------")
        while x != None:
            print("index is ",x, "value is ", self.key[x])
            x = self.next[x]

        y = self.free
        print("free-----------------")
        while y != None:
            print("index is ", y)
            y = self.next[y]

if __name__ == "__main__":
    s = STACK(10)
    for i in range(5):
        s.PUSH(i+10)

    s.PRINT()
    input("")
    for i in range(4):
        print(s.POP())

    s.PRINT()

10.4 有根树的表示





习题解答


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值