简体   繁体   English

Python中的双链表

[英]Doubly Linked list in Python

Hey guys I'm really lost. 嗨,我真的迷路了。 I am writing a Doubly Linked List program for my Data Structures class and I just can't figure it out. 我正在为我的数据结构类编写一个“双链表”程序,但我无法弄清楚。

UPDATE: So I have my singly linked list assignment done. 更新:所以我完成了单链列表分配。 How can I convert it to a doubly linked list and use the data provided to load it in and print it? 如何将其转换为双向链表,并使用提供的数据将其加载并打印出来?

Objective 目的

Program Specification: 程序规格:

  1. Read data for names and weights for 15 people from the console where there is a name on a line followed by a weight on the next line, like in names.txt. 从控制台读取15个人的名称和权重数据,在该行上有一个名称,然后在下一行有一个权重,例如names.txt。

  2. Your program will build a list for the data maintained in ascending order based on both name and weight via a doubly linked list. 您的程序将通过双向链接列表为基于名称和权重的升序维护的数据建立一个列表。

  3. This dll will use one pointer to keep weights in sorted order, and use the other link to keep names on sorted order. 该dll将使用一个指针将权重保持在已排序的顺序,并使用另一个链接将名称保持在已排序的顺序。

  4. You need to build the list as you go maintaining this ordering, so at any time a print method was called it would print the related field in order. 您需要在保持此顺序的同时构建列表,因此在任何时候调用print方法都会按顺序打印相关字段。 (This means nodes are added to the list in sorted order, elements are not added to the list followed by a sort called on the list.) (这意味着节点将按已排序的顺序添加到列表,元素不会添加到列表,后跟列表上调用的排序。)

For example after 3 elements are added for (Name – Weight): Michael – 275, Tom – 150, Abe – 200. 例如,在为(名称–权重)添加3个元素之后:迈克尔– 275,汤姆– 150,安倍– 200。

Output: Names & weights sorted(ascending) by name. 输出:名称和权重按名称排序(升序)。 : Abe – 200, Michael – 275, Tom - 150 Names & weights sorted(ascending) by weight. :安倍– 200,迈克尔– 275,汤姆-150名称和重量按重量排序(升序)。 : Tom – 150, Abe – 200, Michael - 275 :汤姆-150,安倍-200,迈克尔-275

Small piece of code I'm going from 我要从的一小段代码

class LinkedList(object):
    __slots__ = 'prev', 'next', 'value'

ll1 = LinkedList()
ll2 = LinkedList()

if __name__=="__main__":

  f = open("Names.txt","r")

  ll1.value = f.readline()
  ll1.next = ll2
  ll1.prev = None


  ll2.value = f.readline()
  ll2.next = None
  ll2.prev = ll1

  f.close()

  print("Linearly: \n")
  print(ll1.value)
  print(ll1.next.value)

  print("Reversely: \n")
  print(ll2.value)
  print(ll2.prev.value)

My singly Linked list (sorted) program 我的单链接列表(排序)程序

#!/usr/bin/env python

class Node:
  def __init__(self):
    self.data = None
    self.next = None

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

  def addNode(self, data):
    curr = self.head
    if curr is None:
      n = Node()
      n.data = data
      self.head = n
      return

    if curr.data > data:
      n = Node()
      n.data = data
      n.next = curr
      self.head = n
      return

    while curr.next is not None:
      if curr.next.data > data:
        break
      curr = curr.next
    n = Node()
    n.data = data
    n.next = curr.next
    curr.next = n
    return

  def __str__(self):
    data = []
    curr = self.head
    while curr is not None:
      data.append(curr.data)
      curr = curr.next
    return "[%s]" %(', '.join(str(i) for i in data))

  def __repr__(self):
    return self.__str__()

if __name__=="__main__":
  ll = LinkedList()
  num = int(input("Enter a number: "))
  while num != -1:
    ll.addNode(num)
    num = int(input("Enter a number: "))
  c = ll.head
  while c is not None:
    print(c.data)
    c = c.next

Data: Names.txt 数据:Names.txt

Jim
150
Tom
212
Michael
174
Abe
199
Richard
200
April
117
Claire
124
Bobby
109
Bob
156
Kevin
145
Jason
182
Brian
150
Chris
175
Steven
164
Annabelle
99

As you can see I haven't done much. 如您所见,我没有做太多事情。 I am not sure how to load the data in properly and I'm just overall lost. 我不确定如何正确加载数据,但总体上我迷失了。 I'm not sure where to start. 我不确定从哪里开始。 I've looked at a couple examples online but they are just cryptic to me. 我在网上看了几个例子,但它们对我来说只是个谜。

Thank you for any help in advance. 感谢您的任何帮助。 I greatly appreciate it. 我非常感谢。

Here is how I would do it. 这就是我要怎么做。 I suggest that you create a new question or search around for how to read data from a text file. 我建议您创建一个新问题或搜索如何从文本文件中读取数据。

class Node:
  def __init__(self, name, weight):
    self.name = name
    self.weight = weight
    self.prev_name = None
    self.next_name = None
    self.prev_weight = None
    self.next_weight = None


class DLL:
  def __init__(self):
    self.head = Node(None, None)
    self.tail = Node(None, None)
    self.head.next_name = self.tail
    self.head.next_weight = self.tail
    self.tail.prev_name = self.head
    self.tail.prev_weight = self.head

  def add(self, name, weight):
    node = Node(name, weight)

    # add by name
    p = self.head
    while (p.next_name != self.tail) and (p.next_name.name < name):
      p = p.next_name
    node.next_name = p.next_name
    node.prev_name = p
    p.next_name = node
    node.next_name.prev_name = node

    # add by weight
    p = self.head
    while (p.next_weight != self.tail) and (p.next_weight.weight < weight):
      p = p.next_weight
    node.next_weight = p.next_weight
    node.prev_weight = p
    p.next_weight = node
    node.next_weight.prev_weight = node

  def printByName(self):
    p = self.head
    while p.next_name != self.tail:
      print(p.next_name.name, p.next_name.weight)
      p = p.next_name

  def printByWeight(self):
    p = self.head
    while p.next_weight != self.tail:
      print(p.next_weight.name, p.next_weight.weight)
      p = p.next_weight
    return

And some results: 和一些结果:

D = DLL()
D.add("Jim",150)
D.add("Tom",212)
D.add("Michael",174)
D.add("Abe",199)
D.printByName()
  Abe 199
  Jim 150
  Michael 174
  Tom 212
D.printByWeight()
  Jim 150
  Michael 174
  Abe 199
  Tom 212

Given the fact that the problem definition specifies "pointers", python is not a suitable language to implement this. 考虑到问题定义指定了“指针”这一事实,因此python不适合用于实现此目的。 But you can use python variables as "pointers" (or rather references ) because that is what they are; 但是您可以将python变量用作“指针”(或引用 ),因为它们就是它们。 A python variable is just a name for or refrence to an object. python变量只是对象的名称或名称。

But if you want to implement in python, I would use a list ot tuples. 但是,如果您想在python中实现,我将使用列表ot元组。

The first one is a list of (name, weight) tuples. 第一个是(名称,权重)元组的列表。

In [1]: data = [("Michael", 275), ("Tom", 150), ("Abe", 200)]

The order in this list doesn't matter. 此列表中的顺序无关紧要。 Just append new tuples to this list as they arrive. 只需在append组到达时append到此列表中即可。

Now the easy way to do it would be to make shallow copies (which reference the same tuples), and sort them appropriately just before you print them; 现在, 简单的方法是制作浅表副本(引用相同的元组),并在打印它们之前对其进行适当地排序。

In [2]: namelist = [d for d in data]

In [3]: namelist.sort(key=lambda x: x[0])

In [4]: namelist
Out[4]: [('Abe', 200), ('Michael', 275), ('Tom', 150)]

and

In [5]: weightlist = [d for d in data]

In [6]: weightlist.sort(key=lambda x: x[1])

In [7]: weightlist
Out[7]: [('Tom', 150), ('Abe', 200), ('Michael', 275)]

Printing these in the correct sequence is now trivial. 现在,以正确的顺序打印这些内容很简单。

But this is expressly forbidden in the exercise. 但这在练习中被明确禁止 So what you have to do is something like this; 所以您要做的就是这样;

  • Create a new ( name , weight ) tuple 创建一个新的( nameweight )元组
  • Walk the list of tuples sorted by weight and compare the weight in the new tuple with the weight in the existing tuple (hint: use enumerate so you get the index of the tuple in the list). enumerate按权重排序的元组列表,并将新元组中的权重与现有元组中的权重进行比较(提示:使用enumerate以便获得列表中元组的索引)。 As soon as you've found a weight that is greater than the weight of the listed tuple, insert the new tuple in the weight-sorted list. 一旦找到的权重大于列出的元组的权重,则将新的元组insert权重排序列表中。
  • similar for the name-sorted list, but then using the name as the compare value. 对于名称排序列表, 类似 ,但是将名称用作比较值。

Something like this; 像这样的东西;

In [10]: newvalue = ("Eric", 225)

In [11]: for index, (name, weight) in enumerate(weightlist):
   ....:     if newvalue[1] < weight:
   ....:         weightlist.insert(index, newvalue)
   ....:         break
   ....:     

In [12]: weightlist
Out[12]: [('Tom', 150), ('Abe', 200), ('Eric', 225), ('Michael', 275)]

Note that this algorithm assumes that weightlist is already in sorted order! 请注意,这个算法假定weightlist已经是排序顺序!


Another solution that is more in line of the assignment would be to use a dictionary for every person; 另一个与任务相符的解决方案是为每个人使用一个词典。

In [37]: newvalue = {"name": "Eric", "weight": 225, "nextname": None, "nextweight": None}

You will also need the data list to hold all the dictionaries. 您还将需要data列表来保存所有词典。 And you will need two variables startname and startweight to hold the first name and lowest weight respectively. 并且您将需要两个变量startnamestartweight分别保存名字和最低权重。

After you have made a newvalue , you start with comparing newvalue["weight"] to startweight["weight"] . 创建newvalue ,首先将newvalue["weight"]startweight["weight"] If the new weight is smaller than the startweight, then newvalue becomes the new startweight , and newvalue["nextweight"] should be set to the old startweight. 如果新权重小于起始权重,则newvalue变为新的startweight ,并且startweight newvalue["nextweight"]设置为旧的起始权重。 If not, you move to the next item in the list and compare again. 如果不是,则移至列表中的下一项并再次进行比较。 Note that if you want to insert in the chain, you have to change two nextweight attributes! 请注意,如果要插入链中,则必须更改两个 nextweight属性!

This is a double, singly linked list. 这是一个双重单链接列表。 Beginning with startweight and startname you can print both in order by walking both chains. startweightstartname开头,您可以通过走动两条链来依次打印两者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM