下面给出了一些可能的无序列表操作。

  1. List() 创建一个新的空列表。它不需要参数,并返回一个空列表。
  2. add(item) 向列表中添加一个新项。它需要 item 作为参数,并不返回任何内容。假定该 item 不在列表中。
  3. remove(item) 从列表中删除该项。它需要 item 作为参数并修改列表。假设项存在于列表中。 search(item) 搜索列表中的项目。它需要 item 作为参数,并返回一个布尔值。
  4. isEmpty() 检查列表是否为空。它不需要参数,并返回布尔值。
  5. size()返回列表中的项数。它不需要参数,并返回一个整数。
  6. append(item) 将一个新项添加到列表的末尾,使其成为集合中的最后一项。它需要 item 作为参数,并不返回任何内容。假定该项不在列表中。
  7. index(item) 返回项在列表中的位置。它需要 item 作为参数并返回索引。假定该项在列表 中。 insert(pos,item) 在位置 pos 处向列表中添加一个新项。它需要 item 作为参数并不返回 任何内容。假设该项不在列表中,并且有足够的现有项使其有 pos 的位置。
  8. pop() 删除并返回列表中的最后一个项。假设该列表至少有一个项。

pop(pos) 删除并返回位置 pos 处的项。它需要 pos 作为参数并返回项。假定该项在列表中。

实现无序列表:链表

python emd代码 python empty_List

要注意,必须明确地指定链表的第一项的位置。一旦我们知道第一个项在哪里,第一个项可以告诉我们第二个是什么,等等。外部引用通常被称为链表的头。类似地,最后一个项需要知道没有下一个项。

Node 类

链表实现的基本构造块是节点。每个节点对象必须至少保存两个信息。节点的数据字段和保存对下一个节点的引用。下面展示了 Python 实现。要构造一个节点,需要提供该节点的初始数据值。

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

我们创建一个 Node 对象

python emd代码 python empty_链表_02

Python 引用值 None 将在 Node 类和链表本身发挥重要作用。引用 None 代表没有下一个节点。请注意在构造函数中,最初创建的节点 next 被设置为 None。有时这被称为接地节点 ,因此我们使用标准接地符号表示对 None 的引用。

python emd代码 python empty_搜索_03

Unordered List 类

如上所述,无序列表将从一组节点构建,每个节点通过显式引用链接到下一个节点。只要我们知道在哪里找到第一个节点(包含第一个项),之后的每个项可以通过连续跟随下一个链接找到。考虑到这一点,UnorderedList 类必须保持对第一个节点的引用。注意,每个链表对象将维护对链表头部的单个引用。

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

我们构建一个空的链表。赋值语句

>>> mylist = UnorderedList()

创建如 Figure 5 所示的链表。

python emd代码 python empty_链表_04

isEmpty 方法

isEmpty 方法只是检查链表头是否是 None 的引用。

def isEmpty(self): 
    return self.head == None

add 方法

由于该链表是无序的,所以新项相对于已经在列表中的其他项的特定位置并不重要。 新项可以在任何位置。考虑到这一点, 将新项放在最简单的位置是有意义的。 回想一下,链表结构只为我们提供了一个入口点,即链表的头部。所有其他节点只能通过访问第一个节点,然后跟随下一个链接到达。这意味着添加新节点的最简单的地方就在链表的头部。 换句话说,我们将新项作为链表的第一项,现有项将需要链接到这个新项后。

def add(self, item):
    temp = Node(item)
    temp.setNext(self.head)
    self.head = temp
>>>mylist.add(31)
>>>mylist.add(77)
>>>mylist.add(17)
>>>mylist.add(93)
>>>mylist.add(26)
>>>mylist.add(54)

Figure 6展示了链表调用多次add函数的操作

python emd代码 python empty_List_05

因为 31 是添加到链表的第一个项,它最终将是链表中的最后一个节点,因为每个其他项在其前面添加。此外,由于54 是添加的最后一项,它将成为链表的第一个节点中的数据值。

size()、search ()和 remove()方法

size , search 和 remove - 都基于一种称为链表遍历的技术。 遍历是指系统地访问每个节点的过程。为此,我们使用从链表中第一个节点开始的外部引用。当我们访问每个节点时,我们通过“遍历”下一个引用来移动到对下一个节点的引用。要实现 size 方法,我们需要遍历链表并对节点数计数。下面展示了用于计算列表中节点数的 Python 代码。外部引用称为 current ,并在第二行被初始化到链表的头部。

def size(self):
    current = self.head
    count = 0
    while current != None:
        count = count + 1
        current = current.getNext()
    return count

python emd代码 python empty_python emd代码_06

在链表中搜索也使用遍历技术。当我们访问链表中的每个节点时,我们将询问存储在其中的数据是否与我们正在寻找的项匹配。然而,在这种情况下,我们不必一直遍历到列表的末尾。事实上,如果我们到达链表的末尾,这意味着我们正在寻找的项不存在。此外,如果我们找到项,没有必要继续。 以下展示了搜索方法的实现。和在 size 方法中一样,遍历从列表的头部开始初始化。我们还使用一个布尔变量叫 found ,标记我们是否找到了正在寻找的项。

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

remove 方法需要在我们遍历链表时使用两个外部引用。

current 将像之前一样工作, 标记遍历的当前位置。新的引用,我们叫 previous ,将总是传递 current 后面的一个节点 。这样,当 current 停止在要被去除的节点时, previous 将引用链表中用于修改的位置。下面展示了完整的 remove 方法。注意, current 在链表头处开始,和在其他遍历示例中一样。然而, previous 假定总是在current 之后一个节点。因此,由于在 previous 之前没有节点,所以之前的值将为 None(见 Figure 11)。 found 的布尔变量将再次用于控制迭代。这两个语句的顺序是至关重要的。 previous 必须先将一个节点移动到 current的位置。此时,才可以移动 current 。这个过程通常被称为“英寸蠕动”,因为 previous 必须赶上current ,然后current前进。Figure 12 展示了 previous 和 current 的移动,它们沿着链表向下移动,寻找包含值 17 的节点。

python emd代码 python empty_链表_07

python emd代码 python empty_python emd代码_08

一旦 remove 的搜索步骤已经完成,我们需要从链表中删除该节点。 Figure 13 展示了要修改的链接。但是,有一个特殊情况需要解决。如果要删除的项目恰好是链表中的第一个项,则current 将引用链接列表中的第一个节点。这也意味着 previous 是 None。 我们先前说 过,previous 是一个节点,它的下一个节点需要修改。在这种情况下,不是 previous ,而是链表的head 需要改变(见 Figure 14)。

python emd代码 python empty_链表_09

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())