04_python_List

本文介绍了如何使用链表在Python中实现无序表和有序表。无序表通过节点结构存储数据,head属性指向首个节点,支持快速添加、查找和删除操作。有序表在无序表基础上,利用节点排序优化搜索和添加操作,提高效率。链表实现的时间复杂度分析表明,无序表的add操作为O(1),而size、search和remove为O(n)。
摘要由CSDN通过智能技术生成

用链表实现无序表

  • 链表实现:节点Node
    • 每个节点至少要包含2个信息:数据项本身,以及指向下一个节点的引用信息。
    • next为None的意义是指没有下一个节点了
class Node:
    def __init__(self, initdata):
        self.data = initdata
        self.next = None
        
    def getData(self):
        return self.data
    
    def getNext(self):
        return self.next
    
    def setData(self, newdata):
        self.data = newdata
    
    def setNext(self,newnext):
        self.next = newnext

temp = Node(93)
temp.getData()
93
  • 链表实现:无序表UnorderedList
    • 可以采用链接节点的方式构建数据集来实现无序表
    • 链表的第一个和最后一个节点最重要
      • 如果像访问链表中的所有节点,就必须从第一个节点开始沿着链接遍历下去
    • 所以无序表必须要有对第一个节点的引用信息
      • 设立一个属性head,保存对第一个节点的引用
      • 空表的head为None
class UnorderedList:
    def __init__(self):
        self.head = None
        
mylist = UnorderedList()
print(mylist.head)
None
  • 随着数据项的加入,无序表的head始终指向链条中的第一个节点
    • 注意:无序表对象本身并不包含数据项(数据项在节点中),其中包含的head只是对首个节点的引用。
    • 所以isEmpty()方法很容易实现:return self.head == None
  • add():向无序表中添加数据项 O(1)
    • 无序表中没有限定数据项之间的顺序,新数据想可以加入到原表中的任何位置
    • 因为想要访问到整条链上的所有数据项,必须从表头开始,所以添加新数据项最快捷的位置是表头,整条链的首位置。
  • size():从链条头开始遍历到表尾同时用变量累加经过的节点个数 O(n)
  • search():从链头开始遍历到表尾,同时判断当前节点的数据项是否是目标 O(n)
  • remove():首先要找到item,过程同search(),但在删除节点时,需要特别注意:
    • 两种情况分析:
      • current是首个节点:表头head指向current的下一个节点
      • current是位于链条中间的节点:前一个节点的next指向current的下一个节点
class Node:
    def __init__(self, initdata):
        self.data = initdata
        self.next = None
        
    def getData(self):
        return self.data
    
    def getNext(self):
        return self.next
    
    def setData(self, newdata):
        self.data = newdata
    
    def setNext(self,newnext):
        self.next = newnext

class UnorderedList:
    def __init__(self):
        self.head = None
        
    def isEmpty(self):
        return self.head == None

    def add(self, item):
        temp = Node(item)
        temp.setNext(self.head)  #次序!!!二三语句顺序不可颠倒!!!
        self.head = temp

    def size(self):
        current = self.head
        count = 0
        while current != None:
            count = count + 1
            current = current.getNext()
        return count
    
    def search(self, item):
        current = self.head
        found = False
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                current = current.getNext()
        return found
    
    def remove(self, item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()
        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())
            
mylist = UnorderedList()
mylist.add(31)
mylist.add(77)
mylist.add(17)
mylist.add(93)
mylist.add(26)
mylist.add(54)
print(mylist.size())
print(mylist.search(17))
mylist.remove(17)
print(mylist.search(17))
print(mylist.size())
6
True
False
5
class Node:
    def __init__(self, initdata):
        self.data = initdata
        self.next = None
        
    def getData(self):
        return self.data
    
    def getNext(self):
        return self.next
    
    def setData(self, newdata):
        self.data = newdata
    
    def setNext(self,newnext):
        self.next = newnext

class UnorderedList:
    def __init__(self):
        self.head = None
        
    def isEmpty(self):
        return self.head == None

    def add(self, item):
        temp = Node(item)
        temp.setNext(self.head)  #次序!!!二三语句顺序不可颠倒!!!
        self.head = temp

    def size(self):
        current = self.head
        count = 0
        while current != None:
            count = count + 1
            current = current.getNext()
        return count
    
    def search(self, item):
        current = self.head
        found = False
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                current = current.getNext()
        return found
    
    def remove(self, item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()
        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())
    
    def append(self, item):
        temp = Node(item)
        current = self.head

        while current.getNext() != None:
            current = current.getNext()
        
        current.next = temp
    
    def index(self, item):
        count = 0
        current = self.head
        while current != None:
            if current.data == item:
                return count
            else:
                count = count + 1
                current = current.getNext()
        return None
    
    def insert(self, item, pos):
        current = self.head
        nex = None
        temp = Node(item)
        count = 0
        
        if pos == 0:
            temp.setNext(self.head)
            self.head = temp
        else:
            while count != pos - 1:
                count = count + 1
                current = current.getNext()
            nex = current.getNext()
            temp.setNext(nex)
            current.setNext(temp)
     
    def pop(self,pos = -1):
        current = self.head
        count = 0
        nex = None
        num = self.size()
        if pos == 0:
            item = current.data
            self.head = current.getNext()
        elif pos == -1:
            while count != num - 2:
                count = count + 1
                current = current.getNext()
            nex = current.getNext()
            item = nex.getData()
            current.setNext(None)
        else:
            while count != pos - 1:
                count = count + 1
                current = current.getNext()
            nex = current.getNext()
            item = nex.getData()
            current.setNext(nex.getNext())
        return item
 

mylist = UnorderedList()
mylist.add(31) #31
mylist.add(77) #77->31
print(mylist.size())    
mylist.append(23) #77->31->23
print(mylist.size())
print(mylist.index(23))
mylist.insert(6,0) #6->77->31->23
print(mylist.index(6))
mylist.insert(66,1) #6->66->77->31->23
print(mylist.index(66))
print(mylist.index(31))
print(mylist.pop(0)) #66->77->31->23
print(mylist.pop(2)) #66->77->23
print(mylist.pop()) # 66->77
2
3
2
0
1
3
6
31
23

用链表实现有序表

  • 同样采用链表方法实现,Node定义相同。
  • OrderedList也设置一个head来保存链表表头的引用
class Node:
    def __init__(self, initdata):
        self.data = initdata
        self.next = None
        
    def getData(self):
        return self.data
    
    def getNext(self):
        return self.next
    
    def setData(self, newdata):
        self.data = newdata
    
    def setNext(self,newnext):
        self.next = newnext
        
class OrderedList:
    def __init__(self):
        self.head = None
  • 对于isEmpty()/size()/remove()函数与节点的次序无关,其实现同UnorderedList一样。
  • search()/add()方法则需要修改
    • search():在无序表中,如果需要查找的数据项不存在,则会搜索整个链表,直到链尾;而对于有序表来说,可以利用节点有序排列的特性,来为search()节省不存在数据项的查找时间。
      • 一旦当前节点的数据项大于所要查找的数据项,则说明链表后面已经不可能再有要查找的数据项,可以直接返回False。
    • add():改变最大。因为add方法必须保证加入的数据项添加在合适的位置,以维护整个链表的有序性。
      • 涉及到插入位置是在当前节点之前,需要引入一个previous的引用,跟随当前节点current
class Node:
    def __init__(self, initdata):
        self.data = initdata
        self.next = None
        
    def getData(self):
        return self.data
    
    def getNext(self):
        return self.next
    
    def setData(self, newdata):
        self.data = newdata
    
    def setNext(self,newnext):
        self.next = newnext

class OrderedList:
    def __init__(self):
        self.head = None
    
    def isEmpty(self):
        return self.head == None

    def size(self):
        current = self.head
        count = 0
        while current != None:
            count = count + 1
            current = current.getNext()
        return count
    
    def remove(self, item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()
        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())
    
    def search(self, item):
        current = self.head
        found = False
        stop = False
        while current != None and not found and not stop:
            if current.getData() == item:
                found = True
            else:
                if current.getData() > item:
                    stop = True
                else:
                    current = current.getNext()
        return found
    
    def add(self, item):
        current = self.head
        previous = None
        stop = False
        while current != None and not stop:  #发现插入位置
            if current.getData() > item:
                stop = True
            else:
                previous = current
                current = current.getNext()
        temp = Node(item)
        if previous == None:    #插入在表头
            temp.setNext(self.head)
            self.head = temp
        else:               #插入在表中
            temp.setNext(current)
            previous.setNext(temp)

链表实现的算法分析

  • 主要看相应的方法是否涉及到链表的遍历
  • 对一个包含节点数为n的链表:
    • isEmpty():O(1),因为仅需要检查head是否为None
    • size():O(n),需要从表头遍历到表尾
    • search()/remove()以及有序表的add()方法:O(n),因为涉及到链表的遍历。
    • 无序表的add()方法:O(1),因为仅需要插入到表头

  • 链表实现的List,与Python内置的列表数据类型,在有些相同方法的实现上的时间复杂度不同,主要是因为Python内置的列表数据类型是基于顺序存储来实现的,并进行了优化。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值