Python单链表、双向链表和单向循环链表的操作

1、链表的定义:链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址)。

Python单链表、双向链表和单向循环链表的操作_第1张图片

2、单链表的操作:

  • is_empty() 链表是否为空
  • length() 链表长度
  • travel() 遍历整个链表
  • add(item) 链表头部添加元素
  • append(item) 链表尾部添加元素
  • insert(pos, item) 指定位置添加元素
  • remove(item) 删除节点
  • search(item) 查找节点是否存在

3、单链表的判空、长度、遍历、头部尾部添加节点、指定位置添加、查找和删除元素的代码实现

"""单链表的判空、长度、遍历、头部尾部添加节点、指定位置添加、查找和删除元素的代码实现"""
class Node(object):
   """节点"""
   def __init__(self, elem):
      self.elem = elem
      self.next = None

class SingleLinkList(object):
   """单链表"""
   def __init__(self, node=None):
      self.__head = node  #私有属性

   def is_empty(self):
      """链表是否为空"""
      return self.__head == None

   def length(self):
      """链表长度"""
      # cur游标,用来移动遍历节点
      cur = self.__head
      # count记录数据
      count = 0
      while cur != None:
         count += 1
         cur = cur.next
      return count

   def travel(self):
      """遍历整个链表"""
      cur = self.__head
      while cur != None:
         print(cur.elem,end = ' ')
         cur = cur.next
      print(' ')    #换行

   def add(self, item):
      """链表头部添加元素,头插法"""
      node = Node(item)
      node.next = self.__head
      self.__head = node

   def append(self, 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(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
         #当循环退出后,pre指向pos-1位置
         node = Node(item)
         node.next = pre.next
         pre.next = node

   def remove(self, item):
      """删除节点,从前面开始删"""
      cur = self.__head
      pre = None
      while cur != None:
         if cur.elem ==item:
            #先判断此节点是否是头结点
            #是头结点
            if cur == self.__head:
               self.__head = cur.next
            else:
               pre.next = cur.next
            break
         else:
            pre = cur
            cur = cur.next

      return False

   def search(self, item):
      """查找节点是否存在"""
      cur = self.__head
      while cur != None:
         if cur.elem == item:
            return True
         else:
            cur = cur.next
      return False

if __name__ == "__main__":
   ll = SingleLinkList()
   print(ll.is_empty())
   print(ll.length())

   ll.append(1)
   print(ll.is_empty())
   print(ll.length())

   ll.append(2)
   ll.add(8)
   ll.append(4)
   ll.append(5)
   ll.append(6)
   # 8 1 2 3 4 5 6
   ll.insert(-1, 9)   #9 8 1 23456
   ll.travel()
   ll.insert(3, 100)  #9 8 1 100 2 3456
   ll.travel()
   ll.insert(10, 200)  #9 8 1 100 2 3456 200
   ll.travel()
   ll.remove(100)
   ll.travel()
   ll.remove(9)
   ll.travel()
   ll.remove(200)
   ll.travel()

输出:
True
0
False
1
9 8 1 2 4 5 6  
9 8 1 100 2 4 5 6  
9 8 1 100 2 4 5 6 200  
9 8 1 2 4 5 6 200  
8 1 2 4 5 6 200  
8 1 2 4 5 6  

4、链表与顺序表的对比:

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

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

Python单链表、双向链表和单向循环链表的操作_第2张图片

注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。

(1)链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。

(2)顺序表查找很快,主要耗时的操作是拷贝覆盖

5、双向链表:每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值;而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。

Python单链表、双向链表和单向循环链表的操作_第3张图片

6、双向链表的操作:

  • is_empty() 链表是否为空
  • length() 链表长度
  • travel() 遍历链表
  • add(item) 链表头部添加
  • append(item) 链表尾部添加
  • insert(pos, item) 指定位置添加
  • remove(item) 删除节点
  • search(item) 查找节点是否存在

7、双向链表的判空、长度、遍历、头部尾部添加节点、指定位置添加、查找和删除元素的代码实现。

Python单链表、双向链表和单向循环链表的操作_第4张图片

(1)判空、长度、遍历的代码实现与单链表相同。

(2)头部添加节点的代码实现:

def add(self, item):
      """链表头部添加元素,头插法"""
      node = Node(item)  # node是中间那个数
      node.next = self.__head  # self.__head指向的是第一个node的prev
      self.__head = node
      node.next.prev = node  # node.next指向中间的数(node)
      # 或上两行可以执行为self.__head.prev=rode
      # self.__head = node

(3)尾部添加节点的代码实现:

def append(self, 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

(4)指定位置添加的代码实现:

def insert(self, 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
         #当循环退出后,pre指向pos-1位置
         node = Node(item)
         node.next = cur
         node.prev = cur.prev
         cur.prev.next = node   #或先cur.prev = node
         cur.prev = node        #再node.prev.next = node

(5)查找和删除元素的代码实现:

def remove(self, item):
      """删除节点,从前面开始删"""
      cur = self.__head
      while cur != None:
         if cur.elem ==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.next
      return False

def search(self, item):
      """查找节点是否存在"""
      cur = self.__head
      while cur != None:
         if cur.elem == item:
            return True
         else:
            cur = cur.next
      return False

(6)完整代码:

"""双向链表的判空、长度、遍历、尾部添加节点、指定位置添加、查找和删除元素的代码实现"""
class Node(object):
   """节点"""
   def __init__(self, item):
      self.elem = item
      self.next = None
      self.prev = None

class DoubleLinkList(object):
      """双向链表"""
      def __init__(self, node=None):  #与单链表同
         self.__head = node  #私有属性

      def is_empty(self):  #与单链表同
         """链表是否为空"""
         return self.__head is None

      def length(self):  #与单链表同
         """链表长度"""
         # cur游标,用来移动遍历节点
         cur = self.__head
         # count记录数据
         count = 0
         while cur != None:
            count += 1
            cur = cur.next
         return count

      def travel(self):  #与单链表同
         """遍历整个链表"""
         cur = self.__head
         while cur != None:
            print(cur.elem,end = ' ')
            cur = cur.next
         print(' ')    #换行

      def add(self, item):
         """链表头部添加元素,头插法"""
         node = Node(item)  # node是中间那个数
         node.next = self.__head  # self.__head指向的是第一个node的prev
         self.__head = node
         node.next.prev = node  # node.next指向中间的数(node)
         # 或上两行可以执行为self.__head.prev=rode
         # self.__head = node

      def append(self, 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(self, 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
            #当循环退出后,pre指向pos-1位置
            node = Node(item)
            node.next = cur
            node.prev = cur.prev
            cur.prev.next = node   #或先cur.prev = node
            cur.prev = node        #再node.prev.next = node

      def remove(self, item):
         """删除节点,从前面开始删"""
         cur = self.__head
         while cur != None:
            if cur.elem ==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.next
         return False

      def search(self, item):
         """查找节点是否存在"""
         cur = self.__head
         while cur != None:
            if cur.elem == item:
               return True
            else:
               cur = cur.next
         return False

if __name__ == '__main__':
   dll = DoubleLinkList()
   print(dll.is_empty())
   print(dll.length())

   dll.append(1)
   print(dll.is_empty())
   print(dll.length())

   dll.append(2)
   dll.add(8)
   dll.append(3)
   dll.append(4)
   dll.append(5)
   dll.append(6)
   # 8 1 2 3 4 5 6
   dll.insert(-1, 9)  # 9 8 1 23456
   dll.travel()
   dll.insert(3, 100)  # 9 8 1 100 2 3456
   dll.travel()
   dll.insert(10, 200)  # 9 8 1 100 23456 200
   dll.travel()
   dll.remove(100)
   dll.travel()
   dll.remove(9)
   dll.travel()
   dll.remove(200)
   dll.travel()

输出:
True
0
False
1
9 8 1 2 3 4 5 6  
9 8 1 100 2 3 4 5 6  
9 8 1 100 2 3 4 5 6 200  
9 8 1 2 3 4 5 6 200  
8 1 2 3 4 5 6 200  
8 1 2 3 4 5 6

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

Python单链表、双向链表和单向循环链表的操作_第5张图片

9、单向循环链表的操作:

  • is_empty() 判断链表是否为空
  • length() 返回链表的长度
  • travel() 遍历
  • add(item) 在头部添加一个节点
  • append(item) 在尾部添加一个节点
  • insert(pos, item) 在指定位置pos添加节点
  • remove(item) 删除一个节点
  • search(item) 查找节点是否存在

10、单向循环链表的判空、长度、遍历、头部尾部添加节点、指定位置添加、查找和删除元素的代码实现。

"""单链表的判空、长度、遍历、尾部添加节点、指定位置添加、查找和删除元素的代码实现"""
class Node(object):
   """节点"""
   def __init__(self, elem):
      self.elem = elem
      self.next = None

class SingleCircleLinkList(object):
   """单向循环链表"""
   def __init__(self, node=None):  #构造
      self.__head = node   #如果头没有节点就指向None
      if node:             #如果有节点
         node.next = node  #指向它自己

   def is_empty(self):
      """链表是否为空"""
      return self.__head == None

   def length(self):
      """链表长度"""
      if self.is_empty():
         return 0
      # cur游标,用来移动遍历节点
      cur = self.__head
      # count记录数据
      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.__head:
         print(cur.elem, end = ' ')
         cur = cur.next
      #退出循环,cur指向尾节点,但尾节点的元素没打印
      print(cur.elem)

   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 = node  #或cur.next = self.__head

   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 = cur.next  #或先cur.next = node
         cur.next = node       #再node.next = self.__head

   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
         #当循环退出后,pre指向pos-1位置
         node = Node(item)
         node.next = pre.next
         pre.next = node
   def remove(self, item):
      """删除节点,从前面开始删"""
      if self.is_empty():
         return
      cur = self.__head
      pre = None
      while cur.next != self.__head:
         if cur.elem ==item:
            #先判断此节点是否是头结点
            if cur == self.__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.elem == item:
         if cur == self.__head:
            #链表只有一个节点
            self.__head = None
         else:
            pre.next = cur.next  #或pre.next = self.__head

   def search(self, item):
      """查找节点是否存在"""
      if self.is_empty():
         return False
      cur = self.__head
      while cur.next != self.__head:
         if cur.elem == item:
            return True
         else:
            cur = cur.next
      if cur.elem == item:
         return True
      return False

if __name__ == "__main__":
   ll = SingleCircleLinkList()
   print(ll.is_empty())
   print(ll.length())

   ll.append(1)
   print(ll.is_empty())
   print(ll.length())

   ll.append(2)
   ll.add(8)
   ll.append(4)
   ll.append(5)
   ll.append(6)
   # 8 1 2 3 4 5 6
   ll.insert(-1, 9)   #9 8 1 23456
   ll.travel()
   ll.insert(3, 100)  #9 8 1 100 2 3456
   ll.travel()
   ll.insert(10, 200)  #9 8 1 100 2 3456 200
   ll.travel()
   ll.remove(100)
   ll.travel()
   ll.remove(9)
   ll.travel()
   ll.remove(200)
   ll.travel()

输出:
True
0
False
1
9 8 1 2 4 5 6
9 8 1 100 2 4 5 6
9 8 1 100 2 4 5 6 200
9 8 1 2 4 5 6 200
8 1 2 4 5 6 200
8 1 2 4 5 6

 

 

你可能感兴趣的:(python,链表,单链表)