Списки Python и вычислительная сложность [duplicate]

В то время как , что вызывает NullReferenceExceptions и подходит к avoid / fix , такое исключение было рассмотрено в других ответах, что многие программисты не имеют " t узнал еще, как независимо отлаживать такие исключения во время разработки.

В Visual Studio это обычно легко благодаря Visual Studio Debugger .


Во-первых, убедитесь, что правильная ошибка будет обнаружена - см. . Как разрешить нарушение «Исключение System.NullReferenceException» в VS2010? Примечание1

Затем либо Начать с отладки (F5) , либо Приложить [отладчик VS] к запуску процесса . Иногда может быть полезно использовать Debugger.Break , в котором будет предложено запустить отладчик.

Теперь, когда NullReferenceException выбрано (или необработанно), отладчик остановится ( помните правило, указанное выше?) в строке, на которой произошло исключение. Иногда ошибка может быть легко обнаружена.

Например, в следующей строке единственный код, который может , вызывает исключение, если myString имеет значение null. Это можно проверить, посмотрев окно Watch или выполнив выражения в окне Immediate Window .

var x = myString.Trim();

В более сложных случаях, таких как следуя ниже, вам нужно будет использовать один из методов выше (Watch или Immediate Windows) для проверки выражений, чтобы определить, было ли str1 пустым или если str2 имеет значение null.

var x = str1.Trim() + str2.Trim();

Once , где было выбрано исключение, это обычно тривиально по отношению к разуму назад, чтобы выяснить, где введенное значение null было [неправильно] -

. Найдите время, необходимое для понимания причина исключения. Проверьте нулевые выражения. Проверьте предыдущие выражения, которые могли бы привести к таким нулевым выражениям. Добавьте контрольные точки и, по мере необходимости, пройдите через программу. Используйте отладчик.


1 Если Break on Throws слишком агрессивен и отладчик останавливается на NPE в библиотеке .NET или сторонних разработчиков, Break на User-Unhandled можно использовать для ограничения выловленных исключений. Кроме того, VS2012 представляет Just My Code , который я рекомендую также включить.

Если вы отлаживаете с включенным Just My Code, поведение немного отличается. При включенном Just My Code отладчик игнорирует исключения, связанные с привилегиями обычного языка (CLR) первого шанса, которые выходят за пределы My Code и не проходят через My Code

150
задан Claudiu 11 November 2008 в 08:31
поделиться

23 ответа

Следующее - это то, с чем я столкнулся. Это симилятор Riccardo C.'s , в этом потоке, за исключением того, что он печатает числа в порядке, а не наоборот. Я также сделал объект LinkedList Python Iterator, чтобы распечатать список, как обычный нормальный список Python.

class Node:

    def __init__(self, data=None):
        self.data = data
        self.next = None

    def __str__(self):
        return str(self.data)


class LinkedList:

    def __init__(self):
        self.head = None
        self.curr = None
        self.tail = None

    def __iter__(self):
        return self

    def next(self):
        if self.head and not self.curr:
            self.curr = self.head
            return self.curr
        elif self.curr.next:
            self.curr = self.curr.next
            return self.curr
        else:
            raise StopIteration

    def append(self, data):
        n = Node(data)
        if not self.head:
            self.head = n
            self.tail = n
        else:
            self.tail.next = n
            self.tail = self.tail.next


# Add 5 nodes
ll = LinkedList()
for i in range(1, 6):
    ll.append(i)

# print out the list
for n in ll:
    print n

"""
Example output:
$ python linked_list.py
1
2
3
4
5
"""
65
ответ дан Community 26 August 2018 в 19:38
поделиться
  • 1
    Похоже, есть ошибка перед тем, как поставить StopIteration. Если вы собираетесь сохранить текущий узел как внутреннюю часть состояния, вам нужно сбросить его, прежде чем остановить итерацию, чтобы в следующий раз, когда связанный список зациклился, он войдет в ваше первое предложение. – Tim Wilder 30 April 2014 в 04:25
  • 2
    Мне нравится этот ответ. Один nit, я считаю, что X is None предпочтительнее ==. stackoverflow.com/a/2988117/1740227 – mateor 16 August 2014 в 05:17
  • 3
    Это понятно и легко понять – selfboot 1 December 2015 в 02:05
  • 4
    Вторая ветвь insert не является частным случаем третьего, так что вы можете полностью удалить предложение elif? – Jaime 23 January 2016 в 05:49
  • 5
    Вы говорите: вы никогда не использовали отдельно связанный список в Python для любой проблемы, кроме образовательной. Это хорошо для вас :-) Но я могу заверить вас: Есть проблемы в реальном мире, где связанный список обеспечит идеальное решение :-) Вот почему я сначала просмотрел StackOverflow для связанных списков :-) – Regis May 27 January 2017 в 22:30
  • 6
    @RegisMay: не могли бы вы дать ссылку на конкретный пример практического кода? (обратите внимание: это должен быть «отдельный список в Python» и «В реальном мире»: опишите преимущества для вашего примера, например, читаемость, производительность или другое «практическое значение» по вашему выбору). Я сделал аналогичную просьбу в прошлом: через 8 лет нулевые ссылки, за исключением двусвязных списков, используемых в рецептном наборе Raymond Hettinger, - возможно, это может быть объяснено тем, что только программисты, новые для Python, читают этот вопрос - ваш ввод будет ценным и высоко оцененным. – jfs 27 January 2017 в 23:02
  • 7
    Ой, извини. Я не являюсь носителем английского языка и путаю «один связанный список». с "одним связанным списком". Тем не менее мне нужен (двойной) связанный список, который не существует в python. Дека не помогает, поскольку мне нужен прямой доступ к каждому отдельному элементу без итерации по всем элементам. Моя цель: я хочу реализовать кеш. Тем не менее: если мое несовершенство на английском языке делает мои комментарии неуместными, удалите эти комментарии. Извините за неудобства. – Regis May 29 January 2017 в 20:00
  • 8
    Одно практическое преимущество односвязного списка над двусвязными списками или массивами (которые Python использует внутри для списков) состоит в том, что два связанных списка могут совместно использовать хвост. Это очень полезно для динамических алгоритмов, которые требуют сохраненных значений из предыдущих итераций, где общие хвосты списка могут уменьшить сложность памяти от квадратичного до линейного и исключить временные издержки из-за копирования. – saolof 25 June 2017 в 12:08
  • 9
    Эта ссылка rosettacode была примером реального мира, который использует смоделированный связанный список вместо фактического связанного списка. Взгляните на это, перепишите его, чтобы использовать фактический связанный список, для большей ясности и удобочитаемости, и там у вас есть пример реального мира связанного списка, который используется для улучшения существующего кода. И, во-вторых, самый длинный возрастающий алгоритм подпоследовательности используется в реальном мире, в статистике, так что у вас это есть. Что и требовалось доказать :). Помимо этого, давайте просто согласимся не согласиться. :) – Gino 26 September 2017 в 21:06

Вот мое решение:

Реализация

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

  def get_data(self):
    return self.data

  def set_data(self, data):
    self.data = data

  def get_next(self):
    return self.next

  def set_next(self, node):
    self.next = node


# ------------------------ Link List class ------------------------------- #
class LinkList:

  def __init__(self):
    self.head = None

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

  def traversal(self, data=None):
    node = self.head
    index = 0
    found = False
    while node is not None and not found:
      if node.get_data() == data:
        found = True
      else:
        node = node.get_next()
        index += 1
    return (node, index)

  def size(self):
    _, count = self.traversal(None)
    return count

  def search(self, data):
    node, _ = self.traversal(data)
    return node

  def add(self, data):
    node = Node(data)
    node.set_next(self.head)
    self.head = node

  def remove(self, data):
    previous_node = None
    current_node = self.head
    found = False
    while current_node is not None and not found:
      if current_node.get_data() == data:
        found = True
        if previous_node:
          previous_node.set_next(current_node.get_next())
        else:
          self.head = current_node
      else:
        previous_node = current_node
        current_node = current_node.get_next()
    return found

Использование

link_list = LinkList()
link_list.add(10)
link_list.add(20)
link_list.add(30)
link_list.add(40)
link_list.add(50)
link_list.size()
link_list.search(30)
link_list.remove(20)

Идея реализации оригинала

http://interactivepython.org/runestone/static/pythonds/BasicDS/ImplementinganUnorderedListLinkedLists.html

1
ответ дан Abhinav Mehta 26 August 2018 в 19:38
поделиться

Мои 2 цента

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

    def __str__(self):
        return str(self.value)


class LinkedList:
    def __init__(self):
        self.first = None
        self.last = None

    def add(self, x):
        current = Node(x, None)
        try:
            self.last.next = current
        except AttributeError:
            self.first = current
            self.last = current
        else:
            self.last = current

    def print_list(self):
        node = self.first
        while node:
            print node.value
            node = node.next

ll = LinkedList()
ll.add("1st")
ll.add("2nd")
ll.add("3rd")
ll.add("4th")
ll.add("5th")

ll.print_list()

# Result: 
# 1st
# 2nd
# 3rd
# 4th
# 5th
-1
ответ дан Adeel 26 August 2018 в 19:38
поделиться

Пример связанного списка дважды (сохранить как linkedlist.py):

class node:
    def __init__(self, before=None, cargo=None, next=None): 
        self._previous = before
        self._cargo = cargo 
        self._next  = next 

    def __str__(self):
        return str(self._cargo) or None 

class linkedList:
    def __init__(self): 
        self._head = None 
        self._length = 0

    def add(self, cargo):
        n = node(None, cargo, self._head)
        if self._head:
            self._head._previous = n
        self._head = n
        self._length += 1

    def search(self,cargo):
        node = self._head
        while (node and node._cargo != cargo):
            node = node._next
        return node

    def delete(self,cargo):
        node = self.search(cargo)
        if node:
            prev = node._previous
            nx = node._next
            if prev:
                prev._next = node._next
            else:
                self._head = nx
                nx._previous = None
            if nx:
                nx._previous = prev 
            else:
                prev._next = None
        self._length -= 1

    def __str__(self):
        print 'Size of linked list: ',self._length
        node = self._head
        while node:
            print node
            node = node._next

Тестирование (сохранить как test.py):

from linkedlist import node, linkedList

def test():

    print 'Testing Linked List'

    l = linkedList()

    l.add(10)
    l.add(20)
    l.add(30)
    l.add(40)
    l.add(50)
    l.add(60)

    print 'Linked List after insert nodes:'
    l.__str__()

    print 'Search some value, 30:'
    node = l.search(30)
    print node

    print 'Delete some value, 30:'
    node = l.delete(30)
    l.__str__()

    print 'Delete first element, 60:'
    node = l.delete(60)
    l.__str__()

    print 'Delete last element, 10:'
    node = l.delete(10)
    l.__str__()


if __name__ == "__main__":
    test()

Выход:

Testing Linked List
Linked List after insert nodes:
Size of linked list:  6
60
50
40
30
20
10
Search some value, 30:
30
Delete some value, 30:
Size of linked list:  5
60
50
40
20
10
Delete first element, 60:
Size of linked list:  4
50
40
20
10
Delete last element, 10:
Size of linked list:  3
50
40
20
0
ответ дан Andre Araujo 26 August 2018 в 19:38
поделиться

Вот моя простая реализация:

class Node:
    def __init__(self):
        self.data = None
        self.next = None
    def __str__(self):
        return "Data %s: Next -> %s"%(self.data, self.next)

class LinkedList:
    def __init__(self):
        self.head = Node()
        self.curNode = self.head
    def insertNode(self, data):
        node = Node()
        node.data = data
        node.next = None
        if self.head.data == None:
            self.head = node
            self.curNode = node
        else:
            self.curNode.next = node
            self.curNode = node
    def printList(self):
        print self.head

l = LinkedList()
l.insertNode(1)
l.insertNode(2)
l.insertNode(34)

Выход:

Data 1: Next -> Data 2: Next -> Data 34: Next -> Data 4: Next -> None
1
ответ дан Arovit 26 August 2018 в 19:38
поделиться

При использовании неизменяемых связанных списков, используйте непосредственно кортеж Python.

ls = (1, 2, 3, 4, 5)

def first(ls): return ls[0]
def rest(ls): return ls[1:]

На самом деле это простота, и вы можете сохранить дополнительные функции, такие как len (ls), x в ls и т. д.

1
ответ дан Ber 26 August 2018 в 19:38
поделиться
  • 1
    Корреспонденты не имеют характеристик, которые он просил. Ваш rest () - O (n), в отличие от O (1) для связанного списка, так как это подразумевает новую главу. – Brian 11 November 2008 в 14:10
  • 2
    Правильно. Я имею в виду: не запрашивайте связанные списки для реализации вашего алгоритма, а используйте возможности python для оптимального его реализации. Например. итерация по связанному списку - это O (n), как итерация по корте python с использованием «для x в t:». – Ber 11 November 2008 в 20:29
  • 3
    я думаю, что правильный способ использовать кортежи для реализации связанных списков - это принятый ответ здесь. ваш путь использует неизменяемые массивные объекты – Claudiu 11 November 2008 в 22:56
class LinkedList:
    def __init__(self, value):
        self.value = value
        self.next = None

    def insert(self, node):
        if not self.next:
            self.next = node
        else:
            self.next.insert(node)

    def __str__(self):
        if self.next:
            return '%s -> %s' % (self.value, str(self.next))
        else:
            return ' %s ' % self.value

if __name__ == "__main__":
    items = ['a', 'b', 'c', 'd', 'e']    
    ll = None
    for item in items:
        if ll:
            next_ll = LinkedList(item)
            ll.insert(next_ll)
        else:
            ll = LinkedList(item)
    print('[ %s ]' % ll)
0
ответ дан bouzafr 26 August 2018 в 19:38
поделиться

Вот несколько более сложная версия связанного класса списка, с похожим интерфейсом к типам последовательностей python (т. е. поддерживает индексирование, нарезку, конкатенацию с произвольными последовательностями и т. д.). Он должен иметь O (1) prepend, не копировать данные, если только это не требуется, и может использоваться довольно взаимозаменяемо с кортежами.

Это будет не так просто, как пространство или время, как lisp cons cells, так как классы python, очевидно, немного более тяжелы (вы можете немного улучшить ситуацию с помощью «__slots__ = '_head','_tail'», чтобы уменьшить использование памяти). Однако он будет иметь желаемые характеристики производительности.

Пример использования:

>>> l = LinkedList([1,2,3,4])
>>> l
LinkedList([1, 2, 3, 4])
>>> l.head, l.tail
(1, LinkedList([2, 3, 4]))

# Prepending is O(1) and can be done with:
LinkedList.cons(0, l)
LinkedList([0, 1, 2, 3, 4])
# Or prepending arbitrary sequences (Still no copy of l performed):
[-1,0] + l
LinkedList([-1, 0, 1, 2, 3, 4])

# Normal list indexing and slice operations can be performed.
# Again, no copy is made unless needed.
>>> l[1], l[-1], l[2:]
(2, 4, LinkedList([3, 4]))
>>> assert l[2:] is l.next.next

# For cases where the slice stops before the end, or uses a
# non-contiguous range, we do need to create a copy.  However
# this should be transparent to the user.
>>> LinkedList(range(100))[-10::2]
LinkedList([90, 92, 94, 96, 98])

Реализация:

import itertools

class LinkedList(object):
    """Immutable linked list class."""

    def __new__(cls, l=[]):
        if isinstance(l, LinkedList): return l # Immutable, so no copy needed.
        i = iter(l)
        try:
            head = i.next()
        except StopIteration:
            return cls.EmptyList   # Return empty list singleton.

        tail = LinkedList(i)

        obj = super(LinkedList, cls).__new__(cls)
        obj._head = head
        obj._tail = tail
        return obj

    @classmethod
    def cons(cls, head, tail):
        ll =  cls([head])
        if not isinstance(tail, cls):
            tail = cls(tail)
        ll._tail = tail
        return ll

    # head and tail are not modifiable
    @property  
    def head(self): return self._head

    @property
    def tail(self): return self._tail

    def __nonzero__(self): return True

    def __len__(self):
        return sum(1 for _ in self)

    def __add__(self, other):
        other = LinkedList(other)

        if not self: return other   # () + l = l
        start=l = LinkedList(iter(self))  # Create copy, as we'll mutate

        while l:
            if not l._tail: # Last element?
                l._tail = other
                break
            l = l._tail
        return start

    def __radd__(self, other):
        return LinkedList(other) + self

    def __iter__(self):
        x=self
        while x:
            yield x.head
            x=x.tail

    def __getitem__(self, idx):
        """Get item at specified index"""
        if isinstance(idx, slice):
            # Special case: Avoid constructing a new list, or performing O(n) length 
            # calculation for slices like l[3:].  Since we're immutable, just return
            # the appropriate node. This becomes O(start) rather than O(n).
            # We can't do this for  more complicated slices however (eg [l:4]
            start = idx.start or 0
            if (start >= 0) and (idx.stop is None) and (idx.step is None or idx.step == 1):
                no_copy_needed=True
            else:
                length = len(self)  # Need to calc length.
                start, stop, step = idx.indices(length)
                no_copy_needed = (stop == length) and (step == 1)

            if no_copy_needed:
                l = self
                for i in range(start): 
                    if not l: break # End of list.
                    l=l.tail
                return l
            else:
                # We need to construct a new list.
                if step < 1:  # Need to instantiate list to deal with -ve step
                    return LinkedList(list(self)[start:stop:step])
                else:
                    return LinkedList(itertools.islice(iter(self), start, stop, step))
        else:       
            # Non-slice index.
            if idx < 0: idx = len(self)+idx
            if not self: raise IndexError("list index out of range")
            if idx == 0: return self.head
            return self.tail[idx-1]

    def __mul__(self, n):
        if n <= 0: return Nil
        l=self
        for i in range(n-1): l += self
        return l
    def __rmul__(self, n): return self * n

    # Ideally we should compute the has ourselves rather than construct
    # a temporary tuple as below.  I haven't impemented this here
    def __hash__(self): return hash(tuple(self))

    def __eq__(self, other): return self._cmp(other) == 0
    def __ne__(self, other): return not self == other
    def __lt__(self, other): return self._cmp(other) < 0
    def __gt__(self, other): return self._cmp(other) > 0
    def __le__(self, other): return self._cmp(other) <= 0
    def __ge__(self, other): return self._cmp(other) >= 0

    def _cmp(self, other):
        """Acts as cmp(): -1 for self<other, 0 for equal, 1 for greater"""
        if not isinstance(other, LinkedList):
            return cmp(LinkedList,type(other))  # Arbitrary ordering.

        A, B = iter(self), iter(other)
        for a,b in itertools.izip(A,B):
           if a<b: return -1
           elif a > b: return 1

        try:
            A.next()
            return 1  # a has more items.
        except StopIteration: pass

        try:
            B.next()
            return -1  # b has more items.
        except StopIteration: pass

        return 0  # Lists are equal

    def __repr__(self):
        return "LinkedList([%s])" % ', '.join(map(repr,self))

class EmptyList(LinkedList):
    """A singleton representing an empty list."""
    def __new__(cls):
        return object.__new__(cls)

    def __iter__(self): return iter([])
    def __nonzero__(self): return False

    @property
    def head(self): raise IndexError("End of list")

    @property
    def tail(self): raise IndexError("End of list")

# Create EmptyList singleton
LinkedList.EmptyList = EmptyList()
del EmptyList
13
ответ дан Brian 26 August 2018 в 19:38
поделиться
  • 1
    Я думаю, это не так уж и удивительно, но этот 8-летний (!) Пример не работает с python 3 :) – Andy Hayden 14 March 2017 в 08:18
  • 2
    Просьба представить объяснение для new и всего лишь немного общего объяснения. – anukalp 8 August 2017 в 02:02

мой двойной Linked List может быть понятен noobies .. Если ур, знакомый с DS в C, это вполне читаемо.

# LinkedList..

class node:
    def __init__(self):           //Cluster of Nodes' properties 
        self.data=None
        self.next=None
        self.prev=None

class linkedList():
    def __init__(self):
        self.t = node()                    // for future use
        self.cur_node = node()             // current node
        self.start=node()

    def add(self,data):                          // appending the LL

        self.new_node = node()
        self.new_node.data=data
        if self.cur_node.data is None:          
            self.start=self.new_node               //For the 1st node only

        self.cur_node.next=self.new_node
        self.new_node.prev=self.cur_node
        self.cur_node=self.new_node


    def backward_display(self):                  //Displays LL backwards
        self.t=self.cur_node
        while self.t.data is not None:
            print(self.t.data)
            self.t=self.t.prev

    def forward_display(self):                   //Displays LL Forward
        self.t=self.start
        while self.t.data is not None:
            print(self.t.data)
            self.t=self.t.next
            if self.t.next is None:
                print(self.t.data)
                break

    def main(self):                          //This is kind of the main 
                                               function in C
        ch=0
        while ch is not 4:                    //Switch-case in C 
            ch=int(input("Enter your choice:"))
            if ch is 1:
                data=int(input("Enter data to be added:"))
                ll.add(data)
                ll.main()
            elif ch is 2:
                ll.forward_display()
                ll.main()
            elif ch is 3:
                ll.backward_display()
                ll.main()
            else:
                print("Program ends!!")
                return


ll=linkedList()
ll.main()

Хотя к этому коду можно добавить еще много упрощений, я подумал сырая реализация мне более захватывающая.

-1
ответ дан Cold Tison 26 August 2018 в 19:38
поделиться
class LinkedStack:
'''LIFO Stack implementation using a singly linked list for storage.'''

_ToList = []

#---------- nested _Node class -----------------------------
class _Node:
    '''Lightweight, nonpublic class for storing a singly linked node.'''
    __slots__ = '_element', '_next'     #streamline memory usage

    def __init__(self, element, next):
        self._element = element
        self._next = next

#--------------- stack methods ---------------------------------
def __init__(self):
    '''Create an empty stack.'''
    self._head = None
    self._size = 0

def __len__(self):
    '''Return the number of elements in the stack.'''
    return self._size

def IsEmpty(self):
    '''Return True if the stack is empty'''
    return  self._size == 0

def Push(self,e):
    '''Add element e to the top of the Stack.'''
    self._head = self._Node(e, self._head)      #create and link a new node
    self._size +=1
    self._ToList.append(e)

def Top(self):
    '''Return (but do not remove) the element at the top of the stack.
       Raise exception if the stack is empty
    '''

    if self.IsEmpty():
        raise Exception('Stack is empty')
    return  self._head._element             #top of stack is at head of list

def Pop(self):
    '''Remove and return the element from the top of the stack (i.e. LIFO).
       Raise exception if the stack is empty
    '''
    if self.IsEmpty():
        raise Exception('Stack is empty')
    answer = self._head._element
    self._head = self._head._next       #bypass the former top node
    self._size -=1
    self._ToList.remove(answer)
    return answer

def Count(self):
    '''Return how many nodes the stack has'''
    return self.__len__()

def Clear(self):
    '''Delete all nodes'''
    for i in range(self.Count()):
        self.Pop()

def ToList(self):
    return self._ToList
1
ответ дан demosthenes 26 August 2018 в 19:38
поделиться
enter code here
enter code here

class node:
    def __init__(self):
        self.data = None
        self.next = None
class linked_list:
    def __init__(self):
        self.cur_node = None
        self.head = None
    def add_node(self,data):
        new_node = node()
        if self.head == None:
            self.head = new_node
            self.cur_node = new_node
        new_node.data = data
        new_node.next = None
        self.cur_node.next = new_node
        self.cur_node = new_node
    def list_print(self):
        node = self.head
        while node:
            print (node.data)
            node = node.next
    def delete(self):
        node = self.head
        next_node = node.next
        del(node)
        self.head = next_node
a = linked_list()
a.add_node(1)
a.add_node(2)
a.add_node(3)
a.add_node(4)
a.delete()
a.list_print()
-1
ответ дан Divesh Kumar 26 August 2018 в 19:38
поделиться
  • 1
    Вы отвечаете на старый вопрос, у которого уже есть несколько хорошо принятых ответов, и вы не даете никаких объяснений. В чем причина публикации вашей версии? Имеет ли он какую-либо выгоду по сравнению с уже представленными решениями? Или любая другая добавленная стоимость? Измените свой ответ и добавьте некоторое объяснение, чтобы сделать ваш ответ более полным. – honk 30 October 2014 в 18:14

Я поместил в список https://pypi.python.org/pypi/linked_list_mod/

класс списка с одиночным соединением Python 2.x и 3.x] Он тестируется с CPython 2.7, CPython 3.4, Pypy 2.3.1, Pypy3 2.3.1 и Jython 2.7b2 и поставляется с красивым автоматизированным набором тестов.

Он также включает классы LIFO и FIFO.

Они не являются неизменными, хотя.

1
ответ дан dstromberg 26 August 2018 в 19:38
поделиться

llist - Связанные списки типов данных для модуля Python

llist реализуют структуры данных связанных списков. Он поддерживает двусвязный список, т. Е. dllist и односвязную структуру данных sllist.

Объекты dllist

Этот объект представляет структуру данных с двойной связью.

first

Первый объект dllistnode в списке. None, если список пуст.

last

Последний объект dllistnode в списке. Нет, если список пуст.

Объекты dllist также поддерживают следующие методы:

append(x)

Добавьте x в правую сторону списка и вставьте dllistnode.

appendleft(x)

Добавьте x в левую сторону списка и вставьте dllistnode.

appendright(x)

Добавьте x в правую сторону списка и вставьте dllistnode.

clear()

Удалите все узлы из списка.

extend(iterable)

Добавить элементы из iterable в правую сторону списка.

extendleft(iterable)

Добавить элементы из iterable в в левой части списка.

extendright(iterable)

Добавить элементы из iterable в правую сторону списка.

insert(x[, before])

Добавить x в правую сторону списка, если before не указана, или вставьте x в левую сторону dllistnode before. Возврат вставлен dllistnode.

nodeat(index)

Вернуть узел (типа dllistnode) в index.

pop()

Удалите и верните значение элемента с правой стороны списка.

popleft()

Удалите и верните значение элемента из левой части списка.

popright()

Удалить и вернуть значение элемента с правой стороны списка

remove(node)

Удалить node из списка и вернуть элемент, который был сохранен в нем.

dllistnode objects

class llist.dllistnode([value])

Возвращает новый узел с двойным соединением, инициализируется (необязательно) с value.

dllistnode объекты предоставляют следующие атрибуты:

next

Следующий узел в списке. Этот атрибут доступен только для чтения.

prev

Предыдущий узел в списке. Этот атрибут доступен только для чтения.

value

Значение, сохраненное в этом узле. Скомпилировано из этой ссылки

sllist

class llist.sllist([iterable]) Возвращает новый отдельный список, инициализированный элементами из iterable. Если iterable не указан, новый sllist пуст.

Аналогичный набор атрибутов и операций определен для этого объекта sllist. См. эту ссылку для получения дополнительной информации.

3
ответ дан Farhad Maleki 26 August 2018 в 19:38
поделиться

Если вы хотите просто создать простой понравившийся список, обратитесь к этому коду

l = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10]]]]]]]]]]

для визуализации выполнения для этой трески Visit http://www.pythontutor.com/visualize.html#mode=edit

-3
ответ дан Ganesh Pujari 26 August 2018 в 19:38
поделиться

Неизменяемые списки лучше всего представлены через два кортежа, а None - NIL. Чтобы разрешить простую формулировку таких списков, вы можете использовать эту функцию:

def mklist(*args):
    result = None
    for element in reversed(args):
        result = (element, result)
    return result

Чтобы работать с такими списками, я предпочел бы предоставить весь набор функций LISP (то есть сначала, второй, n-й и т. Д.). ), чем введение методов.

16
ответ дан Martin v. Löwis 26 August 2018 в 19:38
поделиться

Класс связанного списка

class LinkedStack:
# Nested Node Class
class Node:
    def __init__(self, element, next):
        self.__element = element
        self.__next = next

    def get_next(self):
        return self.__next

    def get_element(self):
        return self.__element

def __init__(self):
    self.head = None
    self.size = 0
    self.data = []

def __len__(self):
    return self.size

def __str__(self):
    return str(self.data)

def is_empty(self):
    return self.size == 0

def push(self, e):
    newest = self.Node(e, self.head)
    self.head = newest
    self.size += 1
    self.data.append(newest)

def top(self):
    if self.is_empty():
        raise Empty('Stack is empty')
    return self.head.__element

def pop(self):
    if self.is_empty():
        raise Empty('Stack is empty')
    answer = self.head.element
    self.head = self.head.next
    self.size -= 1
    return answer

Использование

from LinkedStack import LinkedStack

x = LinkedStack()

x.push(10)
x.push(25)
x.push(55)


for i in range(x.size - 1, -1, -1):

    print '|', x.data[i].get_element(), '|' ,
    #next object

    if x.data[i].get_next() == None:
        print '--> None'
    else:
        print  x.data[i].get_next().get_element(), '-|---->  ',

Выход

| 55 | 25 -|---->   | 25 | 10 -|---->   | 10 | --> None
1
ответ дан Mina Gabriel 26 August 2018 в 19:38
поделиться

Прежде всего, я предполагаю, что вам нужны связанные списки. На практике вы можете использовать collections.deque, чья текущая реализация CPython представляет собой двусвязный список блоков (каждый блок содержит массив из 62 грузовых объектов). Он включает функциональность связанного списка. Вы также можете найти расширение C, названное llist на pypi. Если вам нужна чистая-Python и простая в использовании реализация связанного списка ADT, вы можете взглянуть на мою следующую минимальную реализацию.

class Node (object):
    """ Node for a linked list. """
    def __init__ (self, value, next=None):
        self.value = value
        self.next = next

class LinkedList (object):
    """ Linked list ADT implementation using class. 
        A linked list is a wrapper of a head pointer
        that references either None, or a node that contains 
        a reference to a linked list.
    """
    def __init__ (self, iterable=()):
        self.head = None
        for x in iterable:
            self.head = Node(x, self.head)

    def __iter__ (self):
        p = self.head
        while p is not None:
            yield p.value
            p = p.next

    def prepend (self, x):  # 'appendleft'
        self.head = Node(x, self.head)

    def reverse (self):
        """ In-place reversal. """
        p = self.head
        self.head = None
        while p is not None:
            p0, p = p, p.next
            p0.next = self.head
            self.head = p0

if __name__ == '__main__':
    ll = LinkedList([6,5,4])
    ll.prepend(3); ll.prepend(2)
    print list(ll)
    ll.reverse()
    print list(ll)
0
ответ дан P. Luo 26 August 2018 в 19:38
поделиться

Я написал это на днях

#! /usr/bin/env python

class node:
    def __init__(self):
        self.data = None # contains the data
        self.next = None # contains the reference to the next node


class linked_list:
    def __init__(self):
        self.cur_node = None

    def add_node(self, data):
        new_node = node() # create a new node
        new_node.data = data
        new_node.next = self.cur_node # link the new node to the 'previous' node.
        self.cur_node = new_node #  set the current node to the new one.

    def list_print(self):
        node = self.cur_node # cant point to ll!
        while node:
            print node.data
            node = node.next



ll = linked_list()
ll.add_node(1)
ll.add_node(2)
ll.add_node(3)

ll.list_print()
61
ответ дан Riccardo 26 August 2018 в 19:38
поделиться
  • 1
    как бы вы могли пройти через список и искать определенный узел с конкретными данными? – locoboy 25 August 2011 в 18:17
  • 2
    @locoboy код для этого был бы похож по логике на код в list_print(). – Dennis 11 December 2013 в 21:28
  • 3
    +1 я прихожу из c ++, может относиться к нему – amar 27 December 2013 в 11:55
class Node(object):
    def __init__(self, data=None, next=None):
        self.data = data
        self.next = next

    def setData(self, data):
        self.data = data
        return self.data

    def setNext(self, next):
        self.next = next

    def getNext(self):
        return self.next

    def hasNext(self):
        return self.next != None


class singleLinkList(object):

    def __init__(self):
        self.head = None

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

    def insertAtBeginning(self, data):
        newNode = Node()
        newNode.setData(data)

        if self.listLength() == 0:
            self.head = newNode
        else:
            newNode.setNext(self.head)
            self.head = newNode

    def insertAtEnd(self, data):
        newNode = Node()
        newNode.setData(data)

        current = self.head

        while current.getNext() != None:
            current = current.getNext()

        current.setNext(newNode)

    def listLength(self):
        current = self.head
        count = 0

        while current != None:
            count += 1
            current = current.getNext()
        return count

    def print_llist(self):
        current = self.head
        print("List Start.")
        while current != None:
            print(current.getData())
            current = current.getNext()

        print("List End.")



if __name__ == '__main__':
    ll = singleLinkList()
    ll.insertAtBeginning(55)
    ll.insertAtEnd(56)
    ll.print_llist()
    print(ll.listLength())
4
ответ дан Sudhanshu Dev 26 August 2018 в 19:38
поделиться

Я просто это как забавная игрушка. Он должен быть неизменным, если вы не трогаете методы подчеркивания с префиксом, и он реализует кучу магии Python, например индексирование, и len.

2
ответ дан Thomas Levine 26 August 2018 в 19:38
поделиться
class LL(object):
    def __init__(self,val):
        self.val = val
        self.next = None

    def pushNodeEnd(self,top,val):
        if top is None:
            top.val=val
            top.next=None
        else:
            tmp=top
            while (tmp.next != None):
                tmp=tmp.next        
            newNode=LL(val)
            newNode.next=None
            tmp.next=newNode

    def pushNodeFront(self,top,val):
        if top is None:
            top.val=val
            top.next=None
        else:
            newNode=LL(val)
            newNode.next=top
            top=newNode

    def popNodeFront(self,top):
        if top is None:
            return
        else:
            sav=top
            top=top.next
        return sav

    def popNodeEnd(self,top):
        if top is None:
            return
        else:
            tmp=top
            while (tmp.next != None):
                prev=tmp
                tmp=tmp.next
            prev.next=None
        return tmp

top=LL(10)
top.pushNodeEnd(top, 20)
top.pushNodeEnd(top, 30)
pop=top.popNodeEnd(top)
print (pop.val)
1
ответ дан user1244663 26 August 2018 в 19:38
поделиться

Для некоторых нужд также может быть полезен deque . Вы можете добавлять и удалять элементы на обоих концах дека по цене O (1).

from collections import deque
d = deque([1,2,3,4])

print d
for x in d:
    print x
print d.pop(), d
148
ответ дан Valentin Lorentz 26 August 2018 в 19:38
поделиться
  • 1
    Хотя deque является полезным типом данных, он не является связанным списком (хотя он реализован с использованием двусвязного списка на уровне C). Поэтому он отвечает на вопрос «что бы вы использовали вместо связанных списков в Python? & Quot; и в этом случае первый ответ должен быть (для некоторых потребностей) обычным списком Python (это также не связанный список). – jfs 19 October 2013 в 21:26
  • 2
    @ J.F.Sebastian: Я почти согласен с тобой :) Я думаю, что этот вопрос отвечает скорее: «Какой питонический способ решить проблему, которая использует связанный список на других языках». Дело не в том, что связанные списки не являются полезными, просто проблемы, когда дека не работает, очень редки. – Emil Stenström 20 October 2013 в 21:46
  • 3
    Он не имеет ничего общего с «Pythonic»: связанный список представляет собой другую структуру данных, чем деку, а в разных операциях две поддержки имеют разные времена работы. – Thanatos 7 April 2014 в 21:48
  • 4
    @ dimo414: Связанные списки обычно запрещают индексирование (нет linked_list[n]), потому что это будет O (n). Dequeues позволяют это и выполняют его в O (1). Однако связанные списки, заданные итератором в списке, могут допускать вложение и удаление O (1), тогда как deques не могут (это O (n), как вектор). (За исключением фронта и конца, где оба deques и связанные списки являются O (1). (Хотя deque, вероятно, амортизируется O (1). Связанный список отсутствует.) – Thanatos 19 July 2014 в 07:39
  • 5
    @MadPhysicist & quot; Он [deque] ведет себя как связанный список почти во всех отношениях, даже если имя отличается. & Quot; - это либо неправильно, либо бессмысленно: это неправильно, потому что связанные списки могут предоставлять различные гарантии сложности времени, например, вы можете удалить элемент (известную позицию) из связанного списка в O (1), в то время как deque не обещает его (это O(n)). Если "почти каждый путь" позволяет игнорировать разницу в большом O, тогда ваше утверждение бессмысленно, потому что мы могли бы использовать встроенный список Python как deque, если бы он не был для pop (0), insert (0, v) больших O-гарантий. – jfs 13 September 2016 в 11:20

Я думаю, что реализация ниже заполняет счет довольно изящно.

'''singly linked lists, by Yingjie Lan, December 1st, 2011'''

class linkst:
    '''Singly linked list, with pythonic features.
The list has pointers to both the first and the last node.'''
    __slots__ = ['data', 'next'] #memory efficient
    def __init__(self, iterable=(), data=None, next=None):
        '''Provide an iterable to make a singly linked list.
Set iterable to None to make a data node for internal use.'''
        if iterable is not None: 
            self.data, self.next = self, None
            self.extend(iterable)
        else: #a common node
            self.data, self.next = data, next

    def empty(self):
        '''test if the list is empty'''
        return self.next is None

    def append(self, data):
        '''append to the end of list.'''
        last = self.data
        self.data = last.next = linkst(None, data)
        #self.data = last.next

    def insert(self, data, index=0):
        '''insert data before index.
Raise IndexError if index is out of range'''
        curr, cat = self, 0
        while cat < index and curr:
            curr, cat = curr.next, cat+1
        if index<0 or not curr:
            raise IndexError(index)
        new = linkst(None, data, curr.next)
        if curr.next is None: self.data = new
        curr.next = new

    def reverse(self):
        '''reverse the order of list in place'''
        current, prev = self.next, None
        while current: #what if list is empty?
            next = current.next
            current.next = prev
            prev, current = current, next
        if self.next: self.data = self.next
        self.next = prev

    def delete(self, index=0):
        '''remvoe the item at index from the list'''
        curr, cat = self, 0
        while cat < index and curr.next:
            curr, cat = curr.next, cat+1
        if index<0 or not curr.next:
            raise IndexError(index)
        curr.next = curr.next.next
        if curr.next is None: #tail
            self.data = curr #current == self?

    def remove(self, data):
        '''remove first occurrence of data.
Raises ValueError if the data is not present.'''
        current = self
        while current.next: #node to be examined
            if data == current.next.data: break
            current = current.next #move on
        else: raise ValueError(data)
        current.next = current.next.next
        if current.next is None: #tail
            self.data = current #current == self?

    def __contains__(self, data):
        '''membership test using keyword 'in'.'''
        current = self.next
        while current:
            if data == current.data:
                return True
            current = current.next
        return False

    def __iter__(self):
        '''iterate through list by for-statements.
return an iterator that must define the __next__ method.'''
        itr = linkst()
        itr.next = self.next
        return itr #invariance: itr.data == itr

    def __next__(self):
        '''the for-statement depends on this method
to provide items one by one in the list.
return the next data, and move on.'''
        #the invariance is checked so that a linked list
        #will not be mistakenly iterated over
        if self.data is not self or self.next is None:
            raise StopIteration()
        next = self.next
        self.next = next.next
        return next.data

    def __repr__(self):
        '''string representation of the list'''
        return 'linkst(%r)'%list(self)

    def __str__(self):
        '''converting the list to a string'''
        return '->'.join(str(i) for i in self)

    #note: this is NOT the class lab! see file linked.py.
    def extend(self, iterable):
        '''takes an iterable, and append all items in the iterable
to the end of the list self.'''
        last = self.data
        for i in iterable:
            last.next = linkst(None, i)
            last = last.next
        self.data = last

    def index(self, data):
        '''TODO: return first index of data in the list self.
    Raises ValueError if the value is not present.'''
        #must not convert self to a tuple or any other containers
        current, idx = self.next, 0
        while current:
            if current.data == data: return idx
            current, idx = current.next, idx+1
        raise ValueError(data)
0
ответ дан Y Lan 26 August 2018 в 19:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: