数据结构和算法----链表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bquau/article/details/88844396
  • 链表的定义

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

  • 链表类型
  1. 单链表

  1. 双链表

    

  1. 循环链表

  1. 双向循环链表

  • 时间复杂度
  1. 单链表

1)、插入操作只需要改变相邻节点的指针就可以,例如将a插入n位置只需将n-1位置的next指针指向a,将anext指针指向n+1。整个操作的时间复杂度为O(1)

2)、删除操作同理只需改变,相邻节点的指针

       3)、查询操作最坏时间复杂度为O(n),与数组的连续存储空间,只需要首地址和下标就能计算出对应的内存地址不同,链表需要根据指针一个节点一个节点地依次遍历之后才能知道想要查找的数据的相应节点的内存地址。时间复杂度为O(n)

     2、双链表

        相对与单链表,双链表多了个前驱指针。由此可知双链表比单链表占用更多的内存空间

        1)、插入操作与单链表类似,只不过单链表插入时。需要遍历查找到该节点和插入节点的前驱节点。虽然插入和删除操作O(1)但查找该节点的操作为O(n),双链表因为有前驱指针所以不需要重新遍历就可以找到前驱节点

        2)、删除操作同理,虽然同为O(1)的时间复杂度,但是理论上双链表会比单链表快一倍。

      3、循环链表

         与单链表类似,只不过循环链表从链尾到链头比较方便。适合处理一些循环结构的数据。例如约瑟夫环

  1. 双向循环链表

就是双向链表加循环链表,如果上面的理解了,这个就比较好理解

  • 深入理解
  1. 指针

C语言中称为指针,pythonjava中称为引用。其功能都是存储期所指向的对象的内存地址

  1. 哨兵简化链表实现难度

针对链表的插入、删除操作,需要对插入第一个结点和删除最后一个节点的情况进行特殊处理。

  • python代码实现

定义链表,并实现单链表反转。以后会添加其他相关代码

class Node(object):
   
def __init__(self,data,next=None):
       
self.data = data
       
self.next = next
class MyLink(object):
   
def __init__(self,data):
       
# 尾指针指向最后一个节点,不包括头结点
       
self.headnode = Node(None)
       
self.rear = None
        #
定义链表
        for
d in data:
            NewNode = Node(d)
           
if self.rear is None:
               
self.rear = NewNode
               
self.headnode.next = NewNode
           
else:
               
self.rear.next = NewNode
               
self.rear = NewNode
    #
打印链表
   
def print_all(self):
        next =
self.headnode.next
       
while next is not None:
           
print(next.data,end=' ')
            next = next.next
       
print()

   
# 头插法实现反转
   
def reverse(self):
       
# 将链表的头结点之后的元素分开来
       
next = self.headnode.next
       
self.headnode.next = None

        while
next is not None:
            NewNode = next
            next = next.next
            NewNode.next =
self.headnode.next
           
self.headnode.next = NewNode

   
# 递归实现
   
def reverse2(self):
        next =
self.headnode.next
       
self.print_next(next)
       
print()

   
def print_next(self,next):
       
if next is None:
           
return

       
self.print_next(next.next)
       
print(next.data,end=' ')

   
def get_last_k_node(self,k):
        advance_node =
self.headnode.next
        behind_node =
self.headnode.next
       
while k>0:
           
if advance_node is None:
               
return None
           
advance_node = advance_node.next
            k -=
1
       
while advance_node is not None:
            advance_node = advance_node.next
            behind_node = behind_node.next

       
return behind_node.data


def main():
    data = [
1,2,3,4,5]
    queue = MyLink(data)
    queue.print_all()
   
print(queue.get_last_k_node(1))
    queue.reverse2()
    queue.reverse()
    queue.print_all()



if __name__ == '__main__':
    main()

链表中环检测

class Node():
    def __init__(self,data,next=None):
        self.data = data
        self.next = next
class MyLink(object):
    def __init__(self,data):
        self.headnode = Node(None)
        self.rear = None
        for d in data:
            NewNode = Node(d)
            if self.rear is None:
                self.rear = NewNode
                self.headnode.next = NewNode
            else:
                self.rear.next = NewNode
                self.rear = NewNode
        #self.rear.next = self.headnode 
    def cry(self):
        slow , fast = self.headnode ,self.headnode
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                 return True
        return False
if __name__ == "__main__":
     data = [1,2,3,4,56,7]
     ml = MyLink(data)
     print(ml.cry())

 

猜你喜欢

转载自blog.csdn.net/bquau/article/details/88844396