• 链表


    单链表:

    单链表的数据结构:每个指针指向想一个结点。

    头插入结点:改变自己的指针指向有一个结点

    链表中间插入:改变前一个结点的指针指向自己,改变自己的指针指向后一个结点

    删除列表的第一个结点:改变头指针指向第二个结点,删除自己的指针。

    删除任意结点:改变前一个结点的指针指向下一个结点。

    代码实现:

    #/usr/bin/python
    #-*- coding: utf-8 -*-
    
    class LNode(object):
        #结点初始化函数, p 即模拟所存放的下一个结点的地址
        #为了方便传参, 设置 p 的默认值为 0
        def __init__(self, data, p=0):
            self.data = data
            self.next = p
    
    
    class LinkList(object):
        def __init__(self):
            self.head = None
    
        #链表初始化函数, 方法类似于尾插
        def initList(self, data):
            #创建头结点
            self.head = LNode(data[0])
            p = self.head
            #逐个为 data 内的数据创建结点, 建立链表
            for i in data[1:]:
                node = LNode(i)
                p.next = node
                p = p.next
    
        #链表判空
        def isEmpty(self):
            if self.head.next == 0:
                print ("Empty List!")
                return 1
            else:
                return 0
    
        #取链表长度
        def getLength(self):
            if self.isEmpty():
                exit(0)
    
            p = self.head
            len = 0
            while p:
                len += 1
                p = p.next
            return len
    
        #遍历链表
        def traveList(self):
            if self.isEmpty():
                exit(0)
            print ('
    link list traving result: ',)
            p = self.head
            while p:
                print (p.data,)
                p = p.next
    
        #链表插入数据函数
        def insertElem(self, key, index):
            if self.isEmpty():
                exit(0)
            if index<0 or index>self.getLength()-1:
                print ("
    Key Error! Program Exit.")
                exit(0)
    
            p = self.head
            i = 0
            while i<=index:
                pre = p
                p = p.next
                i += 1
    
            #遍历找到索引值为 index 的结点后, 在其后面插入结点
            node = LNode(key)
            pre.next = node
            node.next = p
    
        #链表删除数据函数
        def deleteElem(self, index):
            if self.isEmpty():
                exit(0)
            if index<0 or index>self.getLength()-1:
                print ("
    Value Error! Program Exit.")
                exit(0)
    
            i = 0
            p = self.head
            #遍历找到索引值为 index 的结点
            while p.next:
                pre = p
                p = p.next
                i += 1
                if i==index:
                    pre.next = p.next
                    p = None
                    return 1
    
            #p的下一个结点为空说明到了最后一个结点, 删除之即可
            pre.next = None
    
    
    if __name__ == "__main__":
        #初始化链表与数据
        data = [1,7,3,45]
        l = LinkList()
        l.initList(data)
        l.traveList()
    
        #插入结点到索引值为3之后, 值为666
        l.insertElem(666, 3)
        l.traveList()
    
        #删除索引值为4的结点
        l.deleteElem(4)
        l.traveList()
    单链表的增删改查
    class Node(object):
        def __init__(self, data, next=None):
            self.val = data
            self.next = next
    
    
    def fun4(head):
        if head == None:
            return None
        L, M, R = None, None, head
        while R.next != None:
            # 第一次循环时:找一个空节点当尾部,以后的循环中是保存前一个结点,然后将当前节点指向前一个结点
            L = M
            # 找一个变量存储当前节点R
            M = R
            # 取出当前节点的下一个节点,R.next
            R = R.next
            #将当前结点指向前一个结点
            M.next = L
        #R.next为空时跳出循环,此时R.next为尾结点,将此节点指向当前节点,此时就变成了头结点
        R.next = M
        return R
    
    
    # 测试用例
    if __name__ == '__main__':
        l1 = Node(3)
        l1.next = Node(2)
        l1.next.next = Node(1)
        l1.next.next.next = Node(9)
        l1.next.next.next.next = Node(6)
        l1.next.next.next.next.next = Node(7)
        l = fun4(l1)
        print(l.val, l.next.val, l.next.next.val, l.next.next.next.val,l.next.next.next.next.val,l.next.next.next.next.next.val)
    单链表反转

    双向链表:

    双向链表的结构和操作原理:

    删除一个双向链表的结点

    代码实现:

    #-*- encoding:utf-8 -*-
    
    
    class Node(object):
        """双向链表节点"""
        def __init__(self, item):
            self.item = item
            self.next = None
            self.prev = None
    
    
    class DLinkList(object):
        """双向链表"""
        def __init__(self):
            self._head = None
    
        def is_empty(self):
            """判断链表是否为空"""
            return self._head == None
    
        def length(self):
            """返回链表的长度"""
            cur = self._head
            count = 0
            while cur != None:
                count += 1
                cur = cur.next
            return count
    
        def travel(self):
            """遍历链表"""
            cur = self._head
            while cur != None:
                print (cur.item)
                cur = cur.next
            print ("")
    
        def add(self, item):
            """头部插入元素"""
            node = Node(item)
            if self.is_empty():
                # 如果是空链表,将_head指向node
                self._head = node
            else:
                # 将node的next指向_head的头节点
                node.next = self._head
                # 将_head的头节点的prev指向node
                self._head.prev = node
                # 将_head 指向node
                self._head = node
    
        def append(self, item):
            """尾部插入元素"""
            node = Node(item)
            if self.is_empty():
                # 如果是空链表,将_head指向node
                self._head = node
            else:
                # 移动到链表尾部
                cur = self._head
                while cur.next != None:
                    cur = cur.next
                # 将尾节点cur的next指向node
                cur.next = node
                # 将node的prev指向cur
                node.prev = cur
    
    
    
        def search(self, item):
            """查找元素是否存在"""
            cur = self._head
            while cur != None:
                if cur.item == item:
                    return True
                cur = cur.next
            return False
    
        def insert(self, pos, item):
            """在指定位置添加节点"""
            if pos <= 0:
                self.add(item)
            elif pos > (self.length() - 1):
                self.append(item)
            else:
                node = Node(item)
                cur = self._head
                count = 0
                # 移动到指定位置的前一个位置
                while count < (pos - 1):
                    count += 1
                    cur = cur.next
                # 将node的prev指向cur
                node.prev = cur
                # 将node的next指向cur的下一个节点
                node.next = cur.next
                # 将cur的下一个节点的prev指向node
                cur.next.prev = node
                # 将cur的next指向node
                cur.next = node
    
        def remove(self, item):
            """删除元素"""
            if self.is_empty():
                return
            else:
                cur = self._head
                if cur.item == item:
                    # 如果首节点的元素即是要删除的元素
                    if cur.next == None:
                        # 如果链表只有这一个节点
                        self._head = None
                    else:
                        # 将第二个节点的prev设置为None
                        cur.next.prev = None
                        # 将_head指向第二个节点
                        self._head = cur.next
                    return
                while cur != None:
                    if cur.item == item:
                        # 将cur的前一个节点的next指向cur的后一个节点
                        cur.prev.next = cur.next
                        # 将cur的后一个节点的prev指向cur的前一个节点
                        cur.next.prev = cur.prev
                        break
                    cur = cur.next
    
    if __name__ == "__main__":
        ll = DLinkList()
        ll.add(1)
        ll.add(2)
        ll.append(3)
        ll.insert(2, 4)
        ll.insert(4, 5)
        ll.insert(0, 6)
        print ("length:", ll.length())
        ll.travel()
        print (ll.search(3))
        print (ll.search(4))
        ll.remove(1)
        print ("length:", ll.length())
        ll.travel()
    双向链表的增删改查

    二、关于链表的面试题

      1.判断一个链表是否成环并判断环结点:

        答:定义两个变量,变量p1从头部开始一次走一个元素,p2从头部开始一次走两个元素,两个变量相等时,说明这个链表成环。

          当两个变量相等时,走的快的变量p2是走的慢的变量p1的两倍。p1走的路程:环结点前的距离+结点到环内相聚点的距离。p2走的路程为:p1走的路程+环内相遇结点到换节点的距离。这时找找一个变量从头开始一次走一步,和快结点一次走一步,当两个变量相等时,这就是环的结点。

    class Node(object):
        def __init__(self,value=None,next = None):
            self.value = value
            self.next = next
    
    #判断是否成环
    def is_loop(head):
        if head == None:
            return "这个链表不是环"
        p1 = head
        p2 = head
        while p2.next != None and  p2.next.next !=None:
            p1 = p1.next
            p2 = p2.next.next
            if p1 == p2:
                return "这个链表是环"
        return "这个链表不是环"
    
    #确定成环的点
    def loop_point(head):
        if head == None:
            return "这个链表不是环"
        p1 = head
        p2 = head
        while p2.next != None and p2.next.next != None:
            p1 = p1.next
            p2 = p2.next.next
            if p1 == p2:
                fast = head
                while fast != p1:
                    fast = fast.next
                    p1 = p1.next
                return "这个链表是环,环结点是%s" % p1.value
        else:
            return "这个链表不是环"
    if __name__ == "__main__":
         node1 = Node(1)
         node2 = Node(2)
         node3 = Node(3)
         node4 = Node(4)
         node5 = Node(5)
         node1.next = node2
         node2.next = node3
         node3.next = node4
         node4.next = node5
         node5.next = node2
         print(loop_point(node1))
         print(is_loop(node1))
    
    
    #这个链表是环,环结点是2
    #这个链表是环
    判断链表是否成环
  • 相关阅读:
    C# 计算结果四舍五入
    同时执行多条SQL语句
    将一个datatable的值赋给另一个dt的三种方法转
    Oracle中增加、删除、修改字段
    Oracle 某列转为行
    DataList中链接跳转页面传参数
    修改数据库中多个表中的同一个字段的长度(可参照修改成同一字段的列名、注释等)
    克隆表结构
    博客专题
    Rational Rose2003 安装教程
  • 原文地址:https://www.cnblogs.com/ppzhang/p/10387072.html
Copyright © 2020-2023  润新知