zoukankan      html  css  js  c++  java
  • 链表

    单链表:

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

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

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

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

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

    代码实现:

    #/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
    #这个链表是环
    判断链表是否成环
  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/ppzhang/p/10387072.html
Copyright © 2011-2022 走看看