用python实现栈、单链表、双链表

前言

推荐个网站,学习数据结构时可以到 visualgo这个网站,感受认识操作一些数据结构的整个动态执行过程,当我们在用代码实现其数据结构的时候,它能给我们带来一些code的思路

栈(stack),它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。

在这里插入图片描述

栈允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。

python代码实现

class Stack(object):
    def __init__(self,limit = 10):
        self.stack = []
        self.limit = limit
    def push(self,data):
        if len(self.stack) >= self.limit:
            raise IndexError("超出栈顶容量")
        #List append往左加元素
        self.stack.append(data) 
    def pop(self):
        if self.stack:
            return self.stack.pop()
        else:
            raise IndexError("已经空栈")
    def peek(self):
        if self.stack:
            return self.stack[-1]
    def is_empty(self):
        #bool()若没有参数,返回False,判断栈是否为空
        return not bool(self.stack)

    def size(self):
        #查看栈中有几个元素
        return len(self.stack)

    #以上即是实现一个栈的基本代码

    #作业(用栈解决括号匹配问题)
    """算法思路,循环字符串的每一个字符("("或")"),如果是(,直接入栈
    如果是")",先判断栈为不为空,若为空,返回括号匹配错误,若不为空,
    栈pop出一个元素,字符串的字符循环完之后,再判断栈为不为空,若不为空,
    返回括号匹配错误,若不为空,返回括号匹配正确
    """
def balanced_parentheses(str):
    stack = Stack(len(str))
    for char in str:
        if char == "(":
            stack.push(char)
        elif char == ")":
            if stack.size() == 0:
                return False
            stack.pop()
    return stack.is_empty()

if __name__ == "__main__":
    examples  = ["(())","())","(()))"]
    for example in examples:
        print(balanced_parentheses(example))

单链表

链表(linked_list)是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。而单链表中的每个节点只包含一个数据域和一个指针域(尾)。

在这里插入图片描述

想获取对链表的更多认识可戳这篇文章数据结构中的链表,你知道多少?

python代码实现

class Node:
    #初始化链点
    def __init__(self,data):
        self.data = data
        self.next = None

class Link_List:
    #初始化链表,注意初始化链表时head可能不存在
    def __init__(self,head = None):
        self.head = head

    #链表的添加功能
    def append(self,new_element):
        #current当前的
        current = self.head
        #当头部节点存在
        if self.head:
            while current.next:
                current = current.next
            current.next = new_element
        #当头部节点不存在
        else:
            self.head = new_element

    def is_empty(self):
        #判断链表为不为空,只需要判断head为不为空
        return not self.head

    def get_length(self):
        #求链表的长度
        temp  =self.head
        length = 0
        while temp != None:
            length = length + 1
            temp = temp.next
        return length
    
    def insert(self,position,new_element):
        #在链表指定索引处插入元素
        if position < 0 or position > self.get_length():
            raise IndexError("插入位置超出范围")
        temp = self.head
        #当插入位置在第一位时候,把head变为新节点
        if position == 0:
            new_element.next = temp
            self.head = new_element
            return
        i = 0
        while i < position:
            pre = temp
            temp = temp.next
            i+=1
        pre.next = new_element
        new_element.next = temp

    def remove(self,position):
        #删除指定索引的链表元素
        if position < 0 or position > self.get_length():
            raise IndexError("要删除的链表元素超出范围")
        i = 0
        temp = self.head
        while temp != None:
            if position == 0:
                self.head = temp.next
                temp.next = None
                return

            pre = temp
            temp = temp.next
            i+=1
            if i == position:
                pre.next = temp.next
                temp.next = None
                return

    def print_list(self):
        #打印链表元素
        temp = self.head
        while temp is not None:
            print(temp.data)
            temp = temp.next

    def initlist(self,data_list):
        #将列表转为链表
        #创建头结点
        self.head = Node(data_list[0])
        temp = self.head
        #逐个为列表中的元素创建结点
        for i in data_list[1:]:
            node = Node(i)
            temp.next = node
            temp = temp.next
    def reverse(self):
        #将链表反转
        """
        假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3。
        在遍历列表时,将当前节点的 next 指针改为指向前一个元素。
        由于节点没有引用其上一个节点,因此必须事先存储其前一个元素。
        在更改引用之前,还需要另一个指针来存储下一个节点。不要忘记在最后返回新的头引用!
        """
        prev = None
        current = self.head
        while current:
            next_node = current.next
            current.next = prev #遍历每一个结点,使其next指向前一个结点
            prev = current
            current = next_node
        self.head = prev

    #交换两个数据特定的链表元素
    def swapNodes(self,node1,node2):
        #传入的node1和node2是要交换的链表元素的数据,而不是链表元素

        prevD1 = None
        prevD2 = None

        #先判断要实行元素交换的链表是否为空,空退出
        if self.is_empty():
            return

        else:
            #判断要交换的元素数据是否相同,相同退出
            if node1 == node2:
                return
            else:
                #根据node1和node2的值找出要交换的两个链表元素
                D1 = self.head
                while D1 != None and D1.data != node1:
                    prevD1 = D1
                    D1 = D1.next
                D2 = self.head
                while D2 != None and D2.data != node2:
                    prevD2 = D2
                    D2 = D2.next
                
                #如果要交换的D1节点是head,做如下交换
                if prevD1 != None:
                    prevD1.next = D2
                else:
                    self.head = D2

                #如果要交换的D2节点是head,做如下交换
                if prevD2 != None:
                    prevD2.next = D1
                else:
                    self.head = D1

                #如果要交换的D1和D2均不是head,做如下交换
                temp = D1.next
                D1.next = D2.next
                D2.next = temp

if __name__ == "__main__":
    link_list = Link_List()
    link_list.append(Node(5))
    link_list.append(Node(4))
    link_list.append(Node(3))
    link_list.append(Node(2))
    link_list.append(Node(1))
    print("交换前")
    link_list.print_list()
    link_list.swapNodes(1,4)
    print("交换后")
    link_list.print_list()

双链表

双向链表(Double_linked_list)也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向它的前一个结点和他的后一个结点。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

在这里插入图片描述

python代码实现

class Node():
    def __init__(self,data):
        #双链表对比单链表,其中的元素多了一个头指针(prev)
        self.data = data
        self.next = None
        self.prev = None


class DLinkList():

    """双链表它不是循环链表"""    
    def __init__(self):
        self._head = None
    
    #判断链表是否为空
    def is_empty(self):
        return not self._head
    
    #获取链表长度
    def get_length(self):
        count = 0
        current = self._head
        while current:
            count += 1
            current = current.next
        return count

    #打印链表中的元素
    def print_node(self):
        current = self._head
        while current != None:
            print(current.data)
            current = current.next
        print("到尽头了")

    #链表头部添加元素
    def add(self,data):
        new_node = Node(data)
        if self.is_empty():
            self._head = new_node
        else:
            new_node.next = self._head
            self._head.prev = new_node
            self._head = new_node

    #链表尾部插入数据
    def append(self,data):
        new_node = Node(data)

        #循环找到链表尾部元素
        current = self._head
        while current != None:
            current = current.next

        current.next = new_node
        new_node.prev = current

    #查询特定数据的链表元素是否存在
    def search(self,data):
        current = self._head
        while current != None:
            if current.data == data:
                return True
            current = current.next
        return False

    #往特定位置插入链表元素
    def insert(self,position,data):
        #如果position <= 0,均往链表首插入
        if position <= 0:
            self.add(data)
        
        #如果position >= 链表长度,均往链表尾插入
        elif position >= self.get_length:
            self.append(data)
        
        #如果position既不 <= 0和 >= 0,则循环找到position-1的元素,让其尾指针
        #指向插入的元素,让其下一个节点头指针指向插入的元素,而插入的元素的头指针
        #指向位置position-1的元素,尾指针指向指向position-1的元素的下一个元素
        else:
            new_node = Node(data)
            current = self._head
            count = 0
            while count < (position-1):
                count += 1
                current = current.next
            new_node.prev =  current
            new_node.next = current.next
            current.next = new_node
            current.next.prev = new_node
    
    def remove(self,data):
        #删除指定数据的链表元素

        #如果链表为空则删除错误
        if self.is_empty:
            return
        else:
            current = self._head
            if current.data == data:
                if current.next == None:
                    self._head = None
                else:
                    current.next.prev = None
                    self._head = current.next
                return
            while current != None:
                current = current.next
                if current.data == data:
                    current.prev.next = current.next
                    current.next.prev = current.prev
                    break
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章