Python算法详解
上QQ阅读APP看书,第一时间看更新

4.2.2 实践演练——实现完整链表操作

下面的实例文件wanlian.py演示了完整实现链表并进行操作测试的过程。文件wanlian.py的主要实现代码如下所示。

源码路径:daima\第4章\wanlian.py

    #清除单链表
    def clear(self):
         LList.__init__(self)
    #判断单链表是否为空
    def is_empty(self):
         return self._head is None
    #计算单链表元素的个数,有两种方式:遍历列表或返回_num
    def count(self):
         return self._num
         """
         p = self._head
         num = 0
         while p:
              num += 1
              p = p.next
         return num
         """
    def __len__(self):
         p = self._head
         num = 0
         while p:
              num += 1
              p = p.next
         return num
    #在表首端插入元素
    def prepend(self, elem):
         self._head = LNode(elem, self._head)
         self._num += 1
    #删除表首端元素
    def pop(self):
         if self._head is None:
              raise LinkedListUnderflow("in pop")
         e = self._head.elem
         self._head = self._head.next
         self._num -= 1
         return e
    #在表末端插入元素
    def append(self, elem):
         if self._head is None:
              self._head = LNode(elem)
              self._num += 1
              return
         p = self._head
         while p.next:
              p = p.next
         p.next = LNode(elem)
         self._num += 1
    #删除表末端元素
    def pop_last(self):
         if self._head is None:
              raise LinkedListUnderflow("in pop_last")
         p = self._head
         #表中只有一个元素
         if p.next is None:
              e = p.elem
              self._head = None
              self._num -= 1
              return e
         while p.next.next:
              p = p.next
         e = p.next.elem
         p.next = None
         self._num -= 1
         return e
    #发现满足条件的第一个表元素
    def find(self, pred):
         p = self._head
         while p:
              if pred(p.elem):
                   return p.elem
              p = p.next
    #发现满足条件的所有元素
    def filter(self, pred):
         p = self._head
         while p:
              if pred(p.elem):
                   yield p.elem
              p = p.next
    #显示
    def printall(self):
         p = self._head
         while p:
              print(p.elem, end="")
              if p.next:
                    print(", ",end="")
              p = p.next
         print("")
    #查找某个值,列表有的话,返回True,没有的话返回False
    def search(self, elem):
         p = self._head
         foundelem = False
         while p and not foundelem:
             if p.elem == elem:
                   foundelem = True
             else:
                   p = p.next
         return foundelem
    #找出元素第一次出现时的位置
    def index(self, elem):
         p = self._head
         num = -1
         found = False
         while p and not found:
              num += 1
              if p.elem == elem:
                    found = True
              else:
                    p = p.next
         if found:
              return num
         else:
              raise ValueError("%d is not in the list!" % elem)
    #删除第一个出现的elem
    def remove(self, elem):
         p = self._head
         pre = None
         while p:
              if p.elem == elem:
                   if not pre:
                         self._head = p.next
                   else:
                          pre.next = p.next
                   break
              else:
                   pre = p
                   p = p.next
         self._num -= 1
    #在指定位置插入值
    def insert(self, pos, elem):
         #当值大于count时默认在尾端插入
         if pos >= self.count():
              self.append(elem)
         #其他情况
         elif 0<=pos<self.count():
              p = self._head
              pre = None
              num = -1
              while p:
                  num += 1
                  if pos == num:
                       if not pre:
                            self._head = LNode(elem, self._head)
                            self._num += 1
                       else:
                            pre.next = LNode(elem,pre.next)
                            self._num += 1
                       break
                  else:
                       pre = p
                       p = p.next
         else:
              raise IndexError
    #删除表中的第i个元素
    def __delitem__(self, key):
         if key == len(self) - 1:
              #pop_lasy num自减
              self.pop_last()
         elif 0<=key<len(self)-1:
              p = self._head
              pre = None
              num = -1
              while p:
                   num += 1
                   if num == key:
                        if not pre:
                             self._head = pre.next
                             self._num -= 1
                        else:
                             pre.next = p.next
                             self._num -=1
                        break
                   else:
                        pre = p
                        p = p.next
         else:
              raise IndexError
    #根据索引获得该位置的元素
    def __getitem__(self, key):
         if not isinstance(key, int):
              raise TypeError
         if 0<=key<len(self):
              p = self._head
              num = -1
              while p:
                  num += 1
                  if key == num:
                       return p.elem
                  else:
                       p = p.next
         else:
              raise IndexError
    # ==
    def __eq__(self, other):
         #两个都为空列表,则相等
         if len(self)==0 and len(other)==0:
              return True
         #两个列表的元素个数相等,在每个元素都相等的情况下,两个列表相等
         elif len(self) == len(other):
              for i in range(len(self)):
                    if self[i] == other[i]:
                           pass
                    else:
                           return False
              #全部遍历完后,两个列表相等
              return True
         #两个列表的元素个数不相等,返回Fasle
         else:
              return False
    # !=
    def __ne__(self, other):
         if self.__eq__(other):
              return False
         else:
              return True
    # >
    def __gt__(self, other):
         l1 = len(self)
         l2 = len(other)
         if not isinstance(other, LList):
              raise TypeError
         # 1.len(self) = len(other)
         if l1 == l2:
              for i in range(l1):
                    if self[i] == other[i]:
                          continue
                    elif self[i] < other[i]:
                          return False
                    else:
                          return True
              #遍历完都相等的话,说明两个列表相等,所以返回False
              return False
         # 2.len(self) > len(other)
         if l1 > l2:
              for i in range(l2):
                    if self[i] == other[i]:
                          continue
                    elif self[i] < other[i]:
                          return False
                    else:
                    return True
              #遍历完毕,前面的元素全部相等,则列表中元素个数多的一方大
              #if self[l2-1] == other[l2-1]:
              return True
         # 3.len(self) < len(other)
         if l1 < l2:
              for i in range(l1):
                    if self[i] == other[i]:
                          continue
                    elif self[i] < other[i]:
                          return False
                    else:
                    return True
              #遍历完毕,前面的元素全部相等,则列表中元素个数多的一方大
              #if self[l2-1] == other[l2-1]:
              return False
    # <
    def __lt__(self, other):
         #列表相等情况下,>会返回False,<在这里的判断会返回True,有错误。所以要考虑在相等的情况下也为False
         if self.__gt__(other) or self.__eq__(other):
               return False
         else:
               return True
    # >=
    def __ge__(self, other):
         """
         if self.__eq__(other) or self.__gt__(other):
               return True
         else:
               return False
         """
         #大于或等于和小于是完全相反的,所以可以依靠小于实现
         if self.__lt__(other):
               return False
         else:
               return True
    # <=
    def __le__(self, other):
         """
         if self.__eq__(other) or self.__lt__(other):
               return True
         else:
               return False
         """
         ##小于或等于和大于是完全相反的,所以可以依靠大于实现
         if self.__gt__(other):
               return False
        else:
               return True
#example,大于5返回True的函数
def greater_5(n):
     if n>5:
          return True
if __name__=="__main__":
     mlist1 = LList()
     mlist2 = LList()
     mlist1.append(1)
     mlist2.append(1)
     mlist1.append(2)
     mlist2.append(2)
     #mlist1.append(2)
     mlist2.append(6)
     mlist2.append(11)
     mlist2.append(12)
     mlist2.append(14)
     mlist1.printall()
     mlist2.printall()
     #print(mlist1 == mlist2)
     #print(mlist1 != mlist2)
     print(mlist1 <= mlist2)
     mlist2.__delitem__(2)
     mlist2.printall()

执行后会输出:

1, 2
1, 2, 6, 11, 12, 14
True
1, 2, 11, 12, 14