第十章 基本数据结构

10.1 栈和队列

1、栈:先进后出
2、队列:先进先出
3、上溢(overflow):栈或队列已经满了,仍往其中加元素
4、下溢(underflow):栈或队列已经空了,仍执行弹出操作

class Stack(object):
    def __init__(self, limit=3):
        self.stack = []  # 存放元素
        self.limit = limit  # 栈容量极限

    def push(self, data):  # 判断栈是否溢出
        if len(self.stack) >= self.limit:
            raise IndexError('栈已满')
        self.stack.append(data)

    def pop(self):
        if self.stack:
            return self.stack.pop()
        else:
            raise IndexError('pop from an empty stack')  # 空栈不能被弹出

    def peek(self):  # 查看堆栈的最上面的元素
        if self.stack:
            return self.stack[-1]

    def is_empty(self):  # 判断栈是否为空
        return not bool(self.stack)

    def size(self):  # 返回栈的大小
        return len(self.stack)


class Queue:
    def __init__(self, limit=4):
        self.items = []
        self.limit = limit

    def enqueue_head(self, item):
        if len(self.items) == self.limit:  # 上溢
            raise IndexError('队列已满')
            self.items.insert(0, item)
        self.items.append(item)

    def enqueue_tail(self, item):
        if len(self.items) == self.limit:  # 上溢
            raise IndexError('队列已满')
        self.items.append(item)

    def dequeue_head(self):
        if len(self.items) == 0:
            raise IndexError("空队列不能弹出")  # 下溢
        return self.items.pop(0)

    def dequeue_tail(self):
        if len(self.items) == 0:
            raise IndexError("空队列不能弹出")  # 下溢
        return self.items.pop(-1)

    def empty(self):
        return self.size() == 0

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


q = Queue()
q.enqueue_head(1)
q.enqueue_head(2)
q.enqueue_tail(3)
q.enqueue_tail(4)
q.dequeue_head()
q.dequeue_tail()
q.dequeue_head()
print(q.size())
st = Stack()
st.push(1)
st.push(2)
st.push(3)
st.pop()
st.pop()
print(st.pop())
st.pop()

练习

10.1-1

在这里插入图片描述

10.1-2

A栈从1开始向 n n n增长
B栈从 n n n开始向1前进
当推入一个元素两个栈的指针相邻

10.1-3

在这里插入图片描述

10.1-6(两个栈实现一个队)

假设有 A A A栈和 B B B
入队时将所有元素都加入 A A A栈: O ( 1 ) O(1) O(1)
出队时将 A A A栈的元素弹出到 B B B栈, B B B栈再弹出,涉及 B B B栈弹出时: O ( n ) O(n) O(n)

10.1-7(两个队实现一个栈)

假设有 A A A队和 B B B
入栈时将所有元素都加入到 A A A队: O ( 1 ) O(1) O(1)
出栈时将 A A A队的元素弹出到 B B B队,当A队只剩下一个元素时再将该元素弹出: O ( n ) O(n) O(n)

10.2 链表

1、双向链表的每一个元素都是一个对象,每个对象有一个关键字key和两个指针prev和next。
2、要搜索一个有 n n n个元素的链表,search操作必须需要 Θ ( n ) \Theta(n) Θ(n)
3、插入操作为 Θ ( 1 ) \Theta(1) Θ(1)
4、仅删除操作需要 Θ ( n ) \Theta(n) Θ(n),删除特定结点需要 Θ ( n ) \Theta(n) Θ(n),因为要先通过search找到该元素
5、在循环语句中使用哨兵的好处仅在于提高了链表的代码的简洁度,并不会提高速度。

class Node(object):
    """双链表结点"""

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


class BilateralLinkList(object):
    def __init__(self, item=None):
        self.head = Node(item)

    def is_empty(self):
        return self.head is None

    def length(self):
        """链表长度"""
        if self.is_empty():
            return 0
        n = 1
        cur = self.head
        while None != cur.next:
            cur = cur.next
            n += 1
        return n

    def ergodic(self):
        """遍历链表"""
        if self.is_empty():
            raise ValueError('ERROR NULL')
        res = []
        cur = self.head
        res.append(cur.item)
        while None != cur.next:
            cur = cur.next
            res.append(cur.item)
        return res

    def add(self, item):
        """在头部添加节点"""
        node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            node.next = self.head
            self.head.prev = node
            self.head = node

    def append(self, item):
        """在尾部添加节点"""
        if self.is_empty():
            self.add(item)
        else:
            node = Node(item)
            cur = self.head
            while None != cur.next:
                cur = cur.next
            cur.next = node
            node.prev = cur

    def insert(self, index, item):
        """在任意位置插入节点"""
        if index == 0:
            self.add(item)
        elif index + 1 >= self.length():
            self.append(item)
        else:
            n = 1
            node = Node(item)
            cur = self.head
            while node != cur.next:
                pre = cur
                cur = cur.next
                n += 1
                if n == index:
                    break
            pre.next = node
            node.prev = pre
            node.next = cur
            cur.prev = node

    def Search(self, k):
        """链表的搜素"""
        """:return 指向k的指针"""
        cur = self.head
        while cur and cur.item != k:
            cur = cur.next
        return cur

    def remove(self):
        """删除头结点"""
        if self.is_empty():
            return False
        cur = self.head.next
        self.head = self.head.next
        self.head.prev = None

    def find_tail(self):
        """找到并指向尾结点"""
        if self.is_empty():
            return False
        cur = self.head
        while cur.next != None:
            cur = cur.next
        return cur

    def delete(self, k):
        """删除结点"""
        if self.is_empty():
            return False
        elif self.head.item == k:  # 删除头结点
            return self.remove()
        elif self.find_tail().item == k:
            pre = self.find_tail().prev  # 删除尾结点
            pre.next = None
        else:# 删除中间结点
            pre1 = self.Search(k)
            pre1.prev.next = pre1.next
            pre1.next.prev = pre1.prev


b = BilateralLinkList(1)
b.add(0)
b.add(-1)
b.append(2)
print(b.ergodic())
b.insert(4, 3)  # 末端插入情况
print("末端插入:", b.ergodic())
b.insert(2, 1.5)  # 中间插入情况
print("中间插入:", b.ergodic())
b.insert(0, -2)  # 头插入情况
print("头插入:", b.ergodic())
print(b.ergodic())
b.remove()  # 删除头结点
print("删除头", b.ergodic())
b.delete(0)  # 删除尾结点
print("删除中间", b.ergodic())
b.delete(3)  # 删除尾结点
print("删除尾", b.ergodic())

练习

10.2-1(单链表删除和插入操作在o(1)时间)

都可以
插入A: 让A指向链表的头部,然后让头指针指向A
删除 C: 将C的next的值赋给C,然后C指向C的next的next
在这里插入图片描述

10.2-2(单链表实现栈,头插头出)

class Node(object):
    """单表结点"""

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


class Linklist():
    def __init__(self, item=None):
        self.head = Node(item)

    def STACK_EMPTY(self):
        return self.head.item is None

    def PUSH(self, x):#头插
        x = Node(x)
        x.next = self.head
        self.head = x

    def POP(self):
        if self.STACK_EMPTY():
            raise IndexError("underflow")
        x = self.head.item
        self.head = self.head.next
        return x


a = Linklist()
a.PUSH(1)
a.PUSH(2)
a.PUSH(3)
print(a.POP())

10.2-3 单链表实现队列(尾插头出)

class Node(object):
    """单表结点"""

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


"""单链表实现队列"""


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

    def QUEUE_EMPTY(self):
        return self.head is None

    def ENQUEUE(self, x):#尾插
        x = Node(x)
        if self.QUEUE_EMPTY():
            self.head = x
        else:
            cur = self.head
            while cur and cur.next:
                cur = cur.next
            cur.next = x

    def DEQUEUE(self):#头出
        if self.QUEUE_EMPTY():
            raise IndexError("underflow")
        x = self.head.item
        self.head = self.head.next
        return x


a = Linklist()
a.ENQUEUE(1)
a.ENQUEUE(2)
a.ENQUEUE(3)
a.ENQUEUE(4)
print(a.DEQUEUE())
print(a.DEQUEUE())
print(a.DEQUEUE())
print(a.DEQUEUE())
print(a.QUEUE_EMPTY())


10.2-4

x ≠ L . n i l x\not =L.nil x=L.nil x . k e y ≠ L . n i l . k e y x.key \not =L.nil.key x.key=L.nil.key
x . k e y ≠ k x.key \not =k x.key=k x . k e y ≠ k x.key \not =k x.key=k

因为知道 L . n i l . k e y ≠ k L.nil.key\not =k L.nil.key=k所以循环的时候就可将这两行代码合并为 x . k e y ≠ k x.key \not =k x.key=k

10.2-5 使用单向循环链表表实现字典

class Node(object):
    """单表结点"""

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


"""单链表实现队列"""


class Linklist():
    def __init__(self):
        self.head = Node()
        self.size = 0  # 因为有哨兵结点的存在

    def QUEUE_EMPTY(self):
        return self.size == 0
    """O(1)"""
    def INSERT(self, x):# 头插
        x = Node(x)
        x.next = self.head.next
        self.head.next = x
        self.size += 1

    """O(n)"""
    def DELETE(self, x):
        prev = self.head
        while prev.next.item != x:
            if prev.next == self.head:
                print("the element is not exist")
            prev = prev.next
        prev.next = prev.next.next
        self.size -= 1

    """O(n)"""
    def SEARCH(self, k):
        cur = self.head
        while cur.next != self.head and cur.item != k:
            cur = cur.next
        return cur


a = Linklist()
a.INSERT(1)
a.INSERT(2)
a.INSERT(3)
print(a.QUEUE_EMPTY())
a.DELETE(1)
a.DELETE(2)
print(a.SEARCH(3))
a.DELETE(3)
print(a.QUEUE_EMPTY())

10.2-6(合并两个双向循环链表)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

L 1. n i l . p r e v . n e x t = L 2. n i l . n e x t L1.nil.prev.next=L2.nil.next L1.nil.prev.next=L2.nil.next
L 2. n i l . n e x t . p r e v = L 1. n i l . p r e v L2.nil.next.prev=L1.nil.prev L2.nil.next.prev=L1.nil.prev
L 1. n i l . p r e v = L 2. n i l . p r e v L1.nil.prev=L2.nil.prev L1.nil.prev=L2.nil.prev
L 2. n i l . p r e v . n e x t = L 1. n i l L2.nil.prev.next=L1.nil L2.nil.prev.next=L1.nil

10.2-7(翻转单向链表)

需要三个指针:
P 2 P_2 P2定位当前元素, P 1 P_1 P1定位前一个元素, P 3 P_3 P3定位后一个元素

10.4有根树的表示

练习

10.4-1

在这里插入图片描述

10.4-2

##TreeNode定义
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

    def __str__(self):
        return f'(root: {self.val}-[left: {self.left}, right: {self.right}])'
def PRINT_BINARY_TREE(root):
    x = root
    if x != None:
        PRINT_BINARY_TREE(x.left)
        print(x.val)
        PRINT_BINARY_TREE(x.right)


root = TreeNode(18)
root.left = TreeNode(12)
root.right = TreeNode(10)
root.left.left = TreeNode(7)
root.left.right = TreeNode(4)
root.right.left = TreeNode(2)
root.right.right = TreeNode(21)
root.left.right.left = TreeNode(5)
print(root)

PRINT_BINARY_TREE(root)

"""定义结点"""
class Node(object):
    def __init__(self, item):
        self.item = item
        self.left = None
        self.right = None


class Binary_tree(object):
    def __init__(self):
        self.root = None

    """树中添加元素"""
    def add(self, item):
        node = Node(item)
        queue = [self.root]  # 用队列存储根结点
        if self.root is None:
            self.root = node
            return
        while queue:
            cur_node = queue.pop(0)
            if cur_node.left is None:
                cur_node.left = node
                return
            else:
                queue.append(cur_node.left)
            if cur_node.right is None:
                cur_node.right = node
                return
            else:
                queue.append(cur_node.right)
 """先序遍历"""

    def preorder(self, root):
        if root is None:
            return
        print(root.item, end=" ")
        self.preorder(root.left)
        self.preorder(root.right)

    """中序遍历"""

    def inorder(self, root):
        if root is None:
            return
        self.inorder(root.left)
        print(root.item, end=" ")
        self.inorder(root.right)

    """后序遍历"""

    def afterorder(self, root):
        if root is None:
            return
        self.afterorder(root.left)
        self.afterorder(root.right)
        print(root.item, end=" ")
Tree = Binary_tree()
Tree.add(18)
Tree.add(12)
Tree.add(10)
Tree.add(7)
Tree.add(4)
Tree.add(2)
Tree.add(21)
Tree.add(5)
Tree.preorder(Tree.root)#18 12 7 5 4 10 2 21
print(":先序")
Tree.inorder(Tree.root)#5 7 12 4 18 2 10 21
print(":中序")
Tree.afterorder(Tree.root)#5 7 4 12 2 21 10 18
print(":后序")

10.4-3 (使用队列作为辅助结构实现二叉树结点的输出)

"""定义结点"""
class Node(object):
    def __init__(self, item):
        self.item = item
        self.left = None
        self.right = None


class Binary_tree(object):
    def __init__(self):
        self.root = None

    """树中添加元素"""

    def add(self, item):
        node = Node(item)
        queue = [self.root]  # 用队列存储根结点
        if self.root is None:
            self.root = node
            return
        while queue:
            cur_node = queue.pop(0)
            if cur_node.left is None:
                cur_node.left = node
                return
            else:
                queue.append(cur_node.left)
            if cur_node.right is None:
                cur_node.right = node
                return
            else:
                queue.append(cur_node.right)

        """
        按层输出树中的元素
        非递归0(n),队列作为辅助数据结构
        """
    def breath_travel(self):
        if self.root is None:
            return
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            print(cur_node.item, end=" ")
            if cur_node.left is not None:
                queue.append(cur_node.left)
            if cur_node.right is not None:
                queue.append(cur_node.right)
Tree = Binary_tree()
Tree.add(18)
Tree.add(12)
Tree.add(10)
Tree.add(7)
Tree.add(4)
Tree.add(2)
Tree.add(21)
Tree.add(5)
Tree.breath_travel()#18 12 10 7 4 2 21 5 :层序
print(":层序")

10.4-3(栈作辅助输出二叉树的元素)

"""定义结点"""


class Node(object):
    def __init__(self, item):
        self.item = item
        self.left = None
        self.right = None


class Binary_tree(object):
    def __init__(self):
        self.root = None

    """树中添加元素"""

    def add(self, item):
        node = Node(item)
        queue = [self.root]  # 用队列存储根结点
        if self.root is None:
            self.root = node
            return
        while queue:
            cur_node = queue.pop(0)
            if cur_node.left is None:
                cur_node.left = node
                return
            else:
                queue.append(cur_node.left)
            if cur_node.right is None:
                cur_node.right = node
                return
            else:
                queue.append(cur_node.right)

        """
        按层输出树中的元素
        非递归0(n),栈作为辅助数据结构
        """

    def breath_travel(self):
        if self.root is None:
            return
        Stack = [self.root]
        while Stack:
            cur_node = Stack.pop()
            print(cur_node.item, end=" ")
             """因为栈是后入先出所以先检查右边的再检查左边的
            	输出的时候就会先左子后右子"""
            if cur_node.right is not None:
                Stack.append(cur_node.right)
            if cur_node.left is not None:
                Stack.append(cur_node.left)


Tree = Binary_tree()
Tree.add(18)
Tree.add(12)
Tree.add(10)
Tree.add(7)
Tree.add(4)
Tree.add(2)
Tree.add(21)
Tree.add(5)
Tree.breath_travel()

10.4-4(输出左子右兄表示的二叉树元素)

"""定义结点"""


class Tree:
    def __init__(self, val):
        self.val = val
        self.left_child = None
        self.right_bro = None


class Solution:
    def getAllNodeFromTreeByStack(self):
        if not self:
            return []
        resList, stack = [], list()
        stack.append(self)
        while stack:
            node = stack.pop()
            resList.append(node.val)
            if node.right_bro:
                stack.append(node.right_bro)
            if node.left_child:
                stack.append(node.left_child)
        return resList
tree = Tree(0)
tree.left_child = Tree(10)
tree.left_child.right_bro = Tree(12)
tree.left_child.right_bro.right_bro = Tree(-1)
tree.left_child.right_bro.right_bro.right_bro = Tree(93)
tree.left_child.right_bro.right_bro.right_bro.left_child = Tree(100)
print(Solution.getAllNodeFromTreeByStack(tree))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值