Python数据结构(链表)

Python数据结构(链表)

单向链表

单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

表元素域elem用来存放具体的数据

链接域next用来存放下一个节点的位置(python中的标识)

变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点

节点实现
python 复制代码
class node(object):
    def __init__(self,item):
        # __item存放的是数据元素
        self.item = item
        # __next是下一个节点的表示
        self.next = None
单链表的操作
python 复制代码
class node(object):
    def __init__(self,item):
        # __item存放的是数据元素
        self.item = item
        # __next是下一个节点的表示
        self.next = None
        
class SingleLinkList(object):
    def __init__(self,node=None):
        self.head = node # 定义头节点,默认值为Node
        
	def is_empty(): #链表是否为空
        return self.head == None:
        
	def length(): #链表长度
        cur = self.head #cur游标表当前的节点,用来移动遍历节点
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count
    
	def travel(): #遍历整个链表
        cur = self.head
        while cur != None:
            print(cur.item, end=" ")
            cur = cur.next
        print("")
    
    def get_all(self):#查找整个链表数据
        cur = self.head
        res = []
        while True:#遍历整个链表,并转成列表形式
            if cur.next == None:
                if cur.item:
                    res.append(cur.item)
                break
            else:
                if cur.item:
                    res.append(cur.item)
                cur = cur.next
        return res
    
    def reverse_printing(self):
        res = self.get_all()#获取列表形式所有链表数据
        ret =res[::-1]#反转列表
        return ret
    
    def reverse(self):#反转链表
        res = self.reverse_printing()#获取逆序的列表形式链表
        sign1 = self.head#创建游标
        while True:#遍历整个链表,断开各连接,没有指向的数据会被垃圾回收
            if sign1.next == None:
                break
            sign2 = sign1.next
            sign1.next = None
            sign1 = sign2
        sign = self.head
        for ele in res:#根据逆序列表形式链表,重新构建链表
            body = Item(ele)
            sign.next = body
            sign = sign.next
            
    def ReverseList(self): #反转链表            
        cur = self.head         
        pre = None              
        while cur:              
            nextNode = cur.next 
            cur.next = pre      
            pre = cur           
            cur = nextNode      
        return pre              
    
	def add(item): #链表头部添加元素,头插法
        node = Node(item)
        node.next = self.head
        self.head = node
        
	def append(item): #链表尾部添加元素,尾插法
		node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head
            while cur.next != None:
                cur = cur.next
            cur.next = node
            
    def insert(pos,item): #指定位置添加元素
		if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            pre = self.head
            count = 0
            while count < (pos-1):
                count += 1
                pre = pre.next
            # 当循环退出后,pre指向pos-1的位置
            node = Node(item)
            node.next = pre.next
            pre.next = node
        
    def remove(item): #删除节点
        # 双指针
        cur = self.head
        pre = None
        while cur != None:
            if cur.item == item:
                # 先判断此节点是否为头结点
                if cur == self.head:
                    self.head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next
         # 单指针
         pre = self.head
         while pre != None:
            if pre.next.item == item:
                if pre == self.head:
                   self.head = pre.next
                else:
                    pre.next = pre.next.next
                break
             else:
                pre = pre.nex
                
    def search(item): #查找节点是否存在
        cur = self.head
        while cur != None:
            if cur.item == item:
                return True
            else:
                cur = cur.next
        return False
链表与顺序表的对比

链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。

链表与顺序表的各种操作复杂度如下所示:

操作 链表 顺序表
访问元素 O(n) O(1)
在头部插入/删除 O(1) O(n)
在尾部插入/删除 O(n) O(1)
在中间插入/删除 O(n) O(n)

注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。

单向循环链表

单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点

操作
python 复制代码
class Node(object):
    def __init__(self,item):
        self.item = item
        self.next = Node
class SingleCycleLinkList(object): #单向循环链表
    def __init__(self,node=Node):
        self.head = node# 定义头节点
        if node:
            node.next = node
    
    def is_empty(self): #判空
        return self.head = None
    
    def length(self): #链表长度
        if self.is_empty():
            return 0
        cur = self.head
        count = 1
        while cur.next != self.head:
            count += 1
            cur = cur.next
        return count
    
    def travel(self): #遍历链表
        if self.is_empty():
            return
        cur = self.head
        while cur.next != self.next:
            print(cur.item, end=' -> ')
            cur = cur.next
        print(cur.item) #尾节点不能进入循环所以要出循环后打印出来
        
    def add(self,item): #头插法
        node = Node(item)
        if self.is_empty():
            self.head = node
            node.next = node
        else:
            cur = self.head
            while cur.next != self.head:
                 cur = cur.next
            #退出循环后cur指向尾节点
            node.next = self.head
            self.head = node
            cur.next = self.head #cur.next = node
     
    def append(self,item): #尾插法
        node = Node(item)
        if self.is_empty():
            self.head = node
            node.next = node
        else:
            cur = self.head
            while cur.next != self.head:
                cur =cur.next
            node.next = self.head
            cur.next = node
    
    def insert(self,pos,item): #在指定位置插入元素
        if pos < 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            pre = self.head
            count = 0
            while count < (pos-1):
                count += 1
                pre = pre.next
            node = Node(item)
            node.next = pre.next
            pre.next = node
            
     def remove(self,item): #删除节点
        cur = self.head
        pre = None
        while cur.next != self.head:
            if cur.item == item;
                #判断此节点是否为头结点
                if cur == sef.head:
                    #删除是头结点的情况先找到尾节点
                    rear = self.head
                    while rear.next != self.head:
                        rear = rear.next
                    self.head = cur.next
                    rear.next = self.head
                else:
                    #中间节点
                    pre.next = cur.next
                return
            else:
                pre = cur
                cur = cur.next
         #退出循环,cur指向尾节点       
         if cur.item == item:
                if cur == self.head:
                    #链表只有一个节点的情况
                    self.head = None
                else:
                    pre.next = cur.next
           
     def search(self,item): #查找节点
        if self.is_empty():
			return False
        cur = self.head
        while cur.next!= self.head:
            if cur.item = item:
                return True
            else:
                cur = cur.next
        #退出循环,cur指向尾节点
        if cur.item == item:
            return True
        return False
          

双向链表

一种更复杂的链表是"双向链表"或"双面链表"。每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值,而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。

操作
python 复制代码
class Node(object): #应为前几个方法与单链表都一样用面向对象的思想可以把单链表中的类继承过来
    """双链表的节点"""
    def __init__(self, item):
        self.item = item
        self.next = None
        self.prev = None
    def is_empty(): #链表是否为空
        return self.head == None:
        
	def length(): #链表长度
        cur = self.head #cur游标表当前的节点,用来移动遍历节点
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count
    
	def travel(): #遍历整个链表
        cur = self.head
        while cur != None:
            print(cur.item, end=" ")
            cur = cur.next
        print("")

	def add(item): #链表头部添加元素,头插法
        node = Node(item)
        node.next = self.head
        self.head.prev = node
        self.head = node
        
	def append(item): #链表尾部添加元素,尾插法
		node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head
            while cur.next != None:
                cur = cur.next
            cur.next = node
            node.prev = cur
            
    def insert(pos,item): #指定位置添加元素
		if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            cur = self.head
            count = 0
            while count < pos:
                count += 1
                cur = cur.next
            # 当循环退出后,cur指向pos的位置
            node = Node(item)
            node.next = cur
            node.prev = cur.prev
            cur.prev.next = node
            cur.prev = node
        
    def remove(item): #删除节点
         cur = self.head
         while cur != None:
            if cur.item == item:
                if cur == self.head:
                    self.head = cur.next
                    if cur.next: #判断链表是否只有一个节点
                		cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    if cur.next:
                    	cur.next.prev = cur.prev
                break
             else:
                cur = cur.nex
                
    def search(item): #查找节点是否存在
        cur = self.head
        while cur != None:
            if cur.item == item:
                return True
            else:
                cur = cur.next
        return False
相关推荐
_.Switch20 分钟前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
测开小菜鸟1 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
萧鼎3 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸3 小时前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农3 小时前
Python 继承、多态、封装、抽象
开发语言·python
ChoSeitaku3 小时前
链表交集相关算法题|AB链表公共元素生成链表C|AB链表交集存放于A|连续子序列|相交链表求交点位置(C)
数据结构·考研·链表
偷心编程3 小时前
双向链表专题
数据结构
香菜大丸3 小时前
链表的归并排序
数据结构·算法·链表
jrrz08283 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
Python大数据分析@3 小时前
python操作CSV和excel,如何来做?
开发语言·python·excel