链表

单链表:

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

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

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

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

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

代码实现:

#/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 ('\rlink 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 ("\rKey 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 ("\rValue 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
#这个链表是环
判断链表是否成环

 

posted @ 2019-02-16 11:08  X小白的逆袭之旅  阅读(372)  评论(0)    收藏  举报