รายการที่เชื่อมโยงหลาม


178

วิธีที่ง่ายที่สุดในการใช้รายการที่เชื่อมโยงในหลามคืออะไร? '(1 2 3 4 5)ในรูปแบบรายการที่เชื่อมโยงจะถูกกำหนดโดยเพียงแค่ รายการของ Python [1, 2, 3, 4, 5]และ tuples (1, 2, 3, 4, 5)นั้นไม่ใช่รายการเชื่อมโยงและรายการที่เชื่อมโยงมีคุณสมบัติที่ดีเช่นการต่อเวลาคงที่และสามารถอ้างอิงส่วนแยกของพวกเขาได้ ทำให้พวกมันไม่เปลี่ยนรูปและพวกมันก็ง่ายที่จะทำงานด้วย!


11
สิ่งนี้อาจช่วยให้คุณมองเห็นได้ .. pythontutor.com/…

คำตอบ:


69

นี่คือฟังก์ชั่นรายการบางส่วนตามการเป็นตัวแทนของ Martin v. Löwis :

cons   = lambda el, lst: (el, lst)
mklist = lambda *args: reduce(lambda lst, el: cons(el, lst), reversed(args), None)
car = lambda lst: lst[0] if lst else lst
cdr = lambda lst: lst[1] if lst else lst
nth = lambda n, lst: nth(n-1, cdr(lst)) if n > 0 else car(lst)
length  = lambda lst, count=0: length(cdr(lst), count+1) if lst else count
begin   = lambda *args: args[-1]
display = lambda lst: begin(w("%s " % car(lst)), display(cdr(lst))) if lst else w("nil\n")

ที่ไหน w = sys.stdout.write

แม้ว่ารายการที่เชื่อมโยงเป็นสองเท่าจะถูกใช้อย่างมีชื่อเสียงในสูตรชุดที่สั่งของ Raymond Hettinger แต่รายการที่เชื่อมโยงโดยลำพังไม่มีคุณค่าใน Python

ฉันไม่เคยใช้ลิสต์ที่เชื่อมโยงเดี่ยว ๆ ใน Python กับปัญหาใด ๆ ยกเว้นด้านการศึกษา

Thomas Watnedal แนะนำแหล่งข้อมูลทางการศึกษาที่ดีวิธีคิดเหมือนนักวิทยาศาสตร์คอมพิวเตอร์บทที่ 17: รายการที่เชื่อมโยง :

รายการที่เชื่อมโยงคือ:

  • รายการว่างที่แสดงโดยไม่มีหรือ
  • โหนดที่มีวัตถุขนส่งสินค้าและการอ้างอิงไปยังรายการที่เชื่อมโยง

    class Node: 
      def __init__(self, cargo=None, next=None): 
        self.car = cargo 
        self.cdr = next    
      def __str__(self): 
        return str(self.car)
    
    def display(lst):
      if lst:
        w("%s " % lst)
        display(lst.cdr)
      else:
        w("nil\n")

30
คุณพูดว่า: คุณไม่เคยใช้รายการที่เชื่อมโยงเดี่ยวใน Python สำหรับปัญหาใด ๆ ยกเว้นการศึกษา นั่นเป็นสิ่งที่ดีสำหรับคุณ :-) แต่ฉันรับรองได้ว่า: มีปัญหาในโลกแห่งความจริงที่รายการที่เชื่อมโยงจะให้ทางออกที่ดี :-) นั่นเป็นเหตุผลที่ฉันสแกน StackOverflow สำหรับรายการที่เชื่อมโยงในตอนแรก :-)
Regis May

8
@RegisMay: คุณคิดที่จะให้ลิงค์ไปยังตัวอย่างโค้ดเฉพาะหรือไม่? (หมายเหตุ: ควรเป็น "รายการที่เชื่อมโยงโดยลำพังใน Python" "ในโลกแห่งความเป็นจริง": อธิบายถึงประโยชน์สำหรับตัวอย่างของคุณเช่นความสามารถในการอ่านประสิทธิภาพหรืออื่น ๆ "คุณค่าเชิงปฏิบัติ" ที่คุณเลือก) ฉันเคยขอคล้าย ๆ กันมาแล้วในรอบ 8 ปีศูนย์เชื่อมโยงยกเว้นรายการเชื่อมโยงทวีคูณที่ใช้ในสูตรชุดที่สั่งของ Raymond Hettinger - บางทีอาจอธิบายได้ว่ามีเพียงโปรแกรมเมอร์คนใหม่ที่เพิ่งอ่านคำถามนี้ - อินพุตของคุณ จะมีคุณค่าและชื่นชมอย่างมาก
jfs

3
โอ้ขอโทษ. ฉันไม่ใช่เจ้าของภาษาและสับสน "เป็นลิสต์ที่เชื่อมโยงเดี่ยว ๆ " กับ "ลิสต์เดียวที่เชื่อมโยง" อย่างไรก็ตามฉันต้องการรายการเชื่อมโยง (สองครั้ง) ซึ่งไม่มีอยู่ในหลาม Deque ไม่ช่วยเพราะฉันต้องการเข้าถึงองค์ประกอบแต่ละตัวโดยตรงโดยไม่ต้องวนซ้ำองค์ประกอบทั้งหมด เป้าหมายของฉัน: ฉันต้องการใช้แคช อย่างไรก็ตาม: หากความไม่สมบูรณ์ของฉันในภาษาอังกฤษทำให้ความคิดเห็นของฉันไม่ตรงโปรดลบความคิดเห็นเหล่านี้ ขออภัยในความไม่สะดวกใด ๆ.
Regis พฤษภาคม

5
ข้อได้เปรียบในทางปฏิบัติอย่างหนึ่งของรายการที่ลิงก์โดยลำพังมากกว่ารายการหรืออาร์เรย์ที่ลิงก์เป็นสองเท่า (ซึ่ง Python ใช้ภายในสำหรับรายการ) คือรายการที่เชื่อมโยงสองรายการสามารถแชร์หางได้ สิ่งนี้มีประโยชน์มากสำหรับอัลกอริธึมแบบไดนามิกที่ต้องการค่าที่บันทึกไว้จากการทำซ้ำก่อนหน้าซึ่งหางรายการการแบ่งปันสามารถลดความซับซ้อนของหน่วยความจำจากสมการกำลังสองเป็นเชิงเส้นและลดเวลาโอเวอร์เฮดเนื่องจากการคัดลอก
saolof

3
ลิงค์ Rosettacode นั้นเป็นตัวอย่างในโลกแห่งความเป็นจริงซึ่งใช้รายการลิงก์จำลองแทนรายการลิงก์จริง ลองดูเขียนใหม่เพื่อใช้ลิสต์ที่เกิดขึ้นจริงเพื่อความชัดเจนและการอ่านที่ดีขึ้นและคุณมีตัวอย่างโลกแห่งความจริงของลิสต์ที่เชื่อมโยงเพื่อใช้ปรับปรุงโค้ดที่มีอยู่ และประการที่สองอัลกอริธึมที่เพิ่มขึ้นที่ยาวที่สุดถูกนำมาใช้ในโลกแห่งความเป็นจริงในสถิติดังนั้นคุณมีมัน QED :) ยิ่งไปกว่านั้นเราก็เห็นด้วยที่จะไม่เห็นด้วย :)
Gino

158

สำหรับความต้องการบางอย่างdequeอาจมีประโยชน์ คุณสามารถเพิ่มและลบรายการที่ปลายทั้งสองด้านของ 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

16
แม้ว่าdequeจะเป็นชนิดข้อมูลที่มีประโยชน์ แต่ก็ไม่ใช่รายการที่เชื่อมโยง (แม้ว่าจะถูกนำไปใช้งานโดยใช้รายการที่ลิงก์เป็นสองเท่าที่ระดับ C) ดังนั้นจึงตอบคำถาม "คุณจะใช้อะไรแทนรายการที่ลิงก์ใน Python" และในกรณีนั้นคำตอบแรกควรจะเป็นรายการไพ ธ อนสามัญ (สำหรับบางความต้องการ) (มันไม่ใช่รายการที่ลิงก์ด้วย)
jfs

3
@JFSebastian: ฉันเกือบจะเห็นด้วยกับคุณ :) ฉันคิดว่าคำถามคำตอบนี้ค่อนข้าง: "เป็นวิธี pythonic ในการแก้ปัญหาที่ใช้รายการเชื่อมโยงในภาษาอื่น ๆ " ไม่ใช่ว่ารายการที่ลิงก์ไม่ได้มีประโยชน์ แต่เป็นปัญหาที่ deque ไม่ทำงานหายากมาก
Emil Stenström

9
มันไม่เกี่ยวอะไรกับ "Pythonic": รายการที่เชื่อมโยงเป็นโครงสร้างข้อมูลที่แตกต่างจาก deque และในการดำเนินการต่าง ๆ ที่ทั้งสองสนับสนุนพวกเขามีเวลาทำงานที่แตกต่างกัน
Thanatos

4
@ dimo414: รายการที่เชื่อมโยงมักจะห้ามการจัดทำดัชนี (ไม่linked_list[n]) เพราะมันจะเป็น O (n) Dequeues อนุญาตและดำเนินการใน O (1) อย่างไรก็ตามรายการที่เชื่อมโยงซึ่งกำหนดตัววนซ้ำลงในรายการสามารถอนุญาตให้ O (1) การแทรกและการเอาออกได้ในขณะที่ deques ไม่สามารถ (เป็น O (n) เช่นเวกเตอร์) (ยกเว้นที่ด้านหน้าและปลายที่ทั้ง deques และรายการที่เชื่อมโยงเป็นทั้ง O (1) (แม้ว่า deque น่าจะถูกตัดจำหน่าย O (1) รายการที่เชื่อมโยงไม่ได้)
Thanatos

3
@MadPhysicist "มัน [deque] ทำตัวเหมือนรายการที่เชื่อมโยงในเกือบทุกทางแม้ว่าชื่อจะแตกต่างกัน" - มันผิดหรือไม่มีความหมาย: มันผิดเพราะรายการที่เชื่อมโยงอาจให้การรับประกันที่แตกต่างกันสำหรับความซับซ้อนของเวลาเช่นคุณสามารถลบองค์ประกอบ (ตำแหน่งที่รู้จัก) ออกจากรายการที่เชื่อมโยงใน O (1) ในขณะที่ deque ไม่สัญญา คือO(n)) หาก "เกือบทุกวิธี" อนุญาตให้เพิกเฉยความแตกต่างใน O ใหญ่ได้ดังนั้นคำสั่งของคุณจะไม่มีความหมายเพราะเราสามารถใช้ Python builtin list เป็น deque หากไม่มีป๊อป (0), รับประกัน (0, v) big O ค้ำประกัน .
jfs

69

ฉันเขียนสิ่งนี้ขึ้นเมื่อวันก่อน

#! /usr/bin/env python

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


class LinkedList:
    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 = LinkedList()
ll.add_node(1)
ll.add_node(2)
ll.add_node(3)

ll.list_print()

คุณจะสามารถผ่านรายการและค้นหาโหนดเฉพาะด้วยข้อมูลที่เฉพาะเจาะจงได้อย่างไร
locoboy

1
@locoboy list_print()รหัสที่จะทำจะคล้ายในตรรกะรหัสใน
Dennis

แสดงรายการในลำดับย้อนกลับ

35

คำตอบที่ยอมรับนั้นค่อนข้างซับซ้อน นี่คือการออกแบบมาตรฐานมากขึ้น:

L = LinkedList()
L.insert(1)
L.insert(1)
L.insert(2)
L.insert(4)
print L
L.clear()
print L

มันเป็นเรื่องง่ายLinkedListระดับบนพื้นฐานของความตรงไปตรงมา c ++ ออกแบบและบทที่ 17: แสดงการเชื่อมโยงตามคำแนะนำของโทมัส Watnedal

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

    def __str__(self):
        return 'Node ['+str(self.value)+']'

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

    def insert(self, x):
        if self.first == None:
            self.first = Node(x, None)
            self.last = self.first
        elif self.last == self.first:
            self.last = Node(x, None)
            self.first.next = self.last
        else:
            current = Node(x, None)
            self.last.next = current
            self.last = current

    def __str__(self):
        if self.first != None:
            current = self.first
            out = 'LinkedList [\n' +str(current.value) +'\n'
            while current.next != None:
                current = current.next
                out += str(current.value) + '\n'
            return out + ']'
        return 'LinkedList []'

    def clear(self):
        self.__init__()

8
ฉันชอบคำตอบนี้ หนึ่งนิดผมเชื่อว่าเป็นที่ต้องการมากกว่าX is None stackoverflow.com/a/2988117/1740227==
ร่วมงาน

สาขาที่สองinsertไม่ใช่กรณีเฉพาะของสาขาที่สามหรือไม่เพื่อให้คุณสามารถลบelifข้อได้ทั้งหมด?
Jaime

17

รายการที่ไม่เปลี่ยนรูปจะถูกแสดงผ่านสองทูเปิลที่ดีที่สุดโดยไม่มี None ที่เป็นตัวแทนของ NIL หากต้องการอนุญาตการกำหนดรายการอย่างง่ายคุณสามารถใช้ฟังก์ชันนี้:

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

หากต้องการทำงานกับรายการเหล่านี้ฉันควรจัดเตรียมฟังก์ชัน LISP ทั้งหมด (เช่นที่หนึ่งที่สองที่ n และอื่น ๆ ) มากกว่าการแนะนำวิธีการ


13

ต่อไปนี้เป็นรุ่นที่ซับซ้อนกว่าเล็กน้อยของคลาสลิสต์ที่เชื่อมโยงกับอินเทอร์เฟซที่คล้ายกับประเภทลำดับของไพ ธ อน ควรมีการเติม O (1) อย่าคัดลอกข้อมูลเว้นแต่จะต้องการและสามารถใช้งานร่วมกับสิ่งอันดับได้

มันจะไม่เป็นพื้นที่หรือเวลาที่มีประสิทธิภาพเท่าเซลล์ข้อเสียเนื่องจากคลาสงูใหญ่เห็นได้ชัดว่ามีน้ำหนักมากขึ้นเล็กน้อย (คุณสามารถปรับปรุงสิ่งต่าง ๆ ด้วย " __slots__ = '_head','_tail'" เล็กน้อยเพื่อลดการใช้หน่วยความจำ) มันจะมีคุณสมบัติประสิทธิภาพ O ใหญ่ที่ต้องการอย่างไรก็ตาม

ตัวอย่างการใช้งาน:

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

ฉันเดาว่ามันไม่น่าประหลาดใจ แต่ตัวอย่าง 8 ปีนี้ (!) ไม่สามารถใช้งานได้กับ python 3 :)
Andy Hayden

1
โปรดระบุคำอธิบายสำหรับคำอธิบายใหม่และเพียงเล็กน้อย
anukalp

7

llist - ประเภทรายการที่เชื่อมโยงสำหรับ Python

โมดูล llist ใช้โครงสร้างข้อมูลลิสต์ที่ลิงก์ มันสนับสนุนรายการที่เชื่อมโยงเป็นทวีคูณเช่นและโครงสร้างข้อมูลที่เชื่อมโยงโดยลำพังdllistsllist

วัตถุ dllist

วัตถุนี้แสดงให้เห็นโครงสร้างข้อมูลรายการที่เชื่อมโยงเป็นสองเท่า

first

dllistnodeวัตถุแรกในรายการ Noneถ้ารายการว่างเปล่า

last

dllistnodeวัตถุสุดท้ายในรายการ ไม่มีหากรายการว่างเปล่า

วัตถุ dllist ยังสนับสนุนวิธีการต่อไปนี้:

append(x)

เพิ่มไปทางด้านขวาของรายการและการกลับมาแทรกxdllistnode

appendleft(x)

เพิ่มไปทางด้านซ้ายของรายการและการกลับมาแทรกxdllistnode

appendright(x)

เพิ่มไปทางด้านขวาของรายการและการกลับมาแทรกxdllistnode

clear()

ลบโหนดทั้งหมดออกจากรายการ

extend(iterable)

ผนวกองค์ประกอบจากiterableทางด้านขวาของรายการ

extendleft(iterable)

ผนวกองค์ประกอบจากiterableทางด้านซ้ายของรายการ

extendright(iterable)

ผนวกองค์ประกอบจากiterableทางด้านขวาของรายการ

insert(x[, before])

เพิ่มxไปทางด้านขวาของรายการถ้าbeforeไม่ได้ระบุหรือใส่ไปทางด้านซ้ายของx กลับมาแทรกdllistnode beforedllistnode

nodeat(index)

ย้อนกลับโหนด (ประเภทdllistnode) indexที่

pop()

ลบและคืนค่าองค์ประกอบจากด้านขวาของรายการ

popleft()

ลบและคืนค่าองค์ประกอบจากด้านซ้ายของรายการ

popright()

ลบและคืนค่าองค์ประกอบจากด้านขวาของรายการ

remove(node)

ลบออกnodeจากรายการและส่งคืนองค์ประกอบที่เก็บไว้ในนั้น

dllistnode วัตถุ

ชั้น llist.dllistnode([value])

กลับโหนดใหม่ที่เชื่อมโยงทวีคูณรายการเริ่มต้น (ขยะ) valueด้วย

dllistnode วัตถุมีคุณสมบัติดังต่อไปนี้:

next

โหนดถัดไปในรายการ คุณลักษณะนี้เป็นแบบอ่านอย่างเดียว

prev

โหนดก่อนหน้าในรายการ คุณลักษณะนี้เป็นแบบอ่านอย่างเดียว

value

ค่าที่เก็บไว้ในโหนดนี้ รวบรวมจากการอ้างอิงนี้

sllist

ชั้นกลับมาใหม่รายการที่เชื่อมโยงเดี่ยวเริ่มต้นได้ด้วยองค์ประกอบจากllist.sllist([iterable]) iterableหากไม่ระบุ iterable ใหม่sllistจะว่างเปล่า

มีการกำหนดชุดคุณลักษณะและการดำเนินการที่คล้ายคลึงกันสำหรับsllistวัตถุนี้ ดูการอ้างอิงนี้สำหรับข้อมูลเพิ่มเติม


มีแหล่งที่มาสำหรับสิ่งนี้หรือไม่? ใช้งานได้กับ python3 หรือไม่
iggy12345

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

2

ฉันใช้ฟังก์ชั่นเพิ่มเติมนี้กับNick Stinemates

def add_node_at_end(self, data):
    new_node = Node()
    node = self.curr_node
    while node:
        if node.next == None:
            node.next = new_node
            new_node.next = None
            new_node.data = data
        node = node.next

วิธีการที่เขาเพิ่มโหนดใหม่ที่จุดเริ่มต้นในขณะที่ฉันได้เห็นการใช้งานจำนวนมากซึ่งมักจะเพิ่มโหนดใหม่ในตอนท้าย แต่อะไรก็ตามมันสนุกที่จะทำ


2

ต่อไปนี้เป็นสิ่งที่ฉันมาด้วย มันคือ similer ของRiccardo C.ในชุดข้อความนี้ยกเว้นมันจะพิมพ์ตัวเลขตามลำดับแทนที่จะเรียงกลับกัน ฉันยังสร้างวัตถุ 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
"""

ดูเหมือนว่ามีข้อผิดพลาดก่อนที่จะยกระดับ StopIteration หากคุณจะเก็บโหนดปัจจุบันเป็นสถานะภายในคุณต้องรีเซ็ตก่อนที่จะหยุดการทำซ้ำเพื่อให้ครั้งต่อไปที่รายการที่เชื่อมโยงถูกวนซ้ำมันจะเข้าสู่ประโยคแรกของคุณ
Tim Wilder

2

ฉันเพิ่งทำสิ่งนี้เป็นของเล่นที่สนุก lenมันควรจะเปลี่ยนรูปตราบใดที่คุณไม่ได้สัมผัสวิธีการขีดนำหน้าและจะดำเนินพวงของเวทมนตร์งูใหญ่เช่นการจัดทำดัชนีและ


1

เมื่อใช้รายการลิงก์ที่ไม่เปลี่ยนรูปแบบให้พิจารณาใช้ tuple ของ Python โดยตรง

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

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

มันสะดวกสบายมากและคุณจะต้องเพิ่มฟังก์ชั่นเพิ่มเติมเช่น len (ls), x เป็น ls, ฯลฯ


Tuples ไม่มีคุณสมบัติด้านประสิทธิภาพที่เขาต้องการ ส่วนที่เหลือของคุณ () คือ O (n) ซึ่งตรงข้ามกับ O (1) สำหรับรายการที่เชื่อมโยงเช่นเดียวกับที่กำลังสร้างหัวใหม่
Brian

ขวา. จุดของฉันคือ: อย่าขอรายการที่เชื่อมโยงเพื่อใช้อัลกอริทึมของคุณ แต่ใช้คุณลักษณะของหลามเพื่อนำไปใช้อย่างเหมาะสมที่สุด เช่น iterating กว่ารายการที่เชื่อมโยงเป็น O (n) เป็นที่ iterating กว่า tuple หลามใช้ "สำหรับ x ใน T:"
เบอร์

ฉันคิดว่าวิธีที่ถูกต้องในการใช้สิ่งอันดับในการใช้รายการที่ลิงก์คือคำตอบที่ยอมรับได้ที่นี่ วิธีการของคุณใช้อาเรย์เหมือนวัตถุที่ไม่เปลี่ยนรูปแบบ
Claudiu

1
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

ฉันใส่คลาสรายการ Python 2.x และ 3.x ที่เชื่อมโยงเดี่ยวที่https://pypi.python.org/pypi/linked_list_mod/

มันทดสอบกับ CPython 2.7, CPython 3.4, Pypy 2.3.1, Pypy3 2.3.1 และ Jython 2.7b2 และมาพร้อมกับชุดทดสอบอัตโนมัติที่ดี

นอกจากนี้ยังมีคลาส LIFO และ FIFO

พวกเขาไม่เปลี่ยนรูปแม้ว่า


1
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

ระดับรายการที่เชื่อมโยง

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

นี่คือการดำเนินการที่เรียบง่ายของฉัน:

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

นี่คือทางออกของฉัน:

การดำเนินงาน

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


0

ฉันคิดว่าการใช้งานด้านล่างเติมเงินอย่างงดงาม

'''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
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

ก่อนอื่นฉันคิดว่าคุณต้องการรายการที่เชื่อมโยง ในทางปฏิบัติคุณสามารถใช้collections.dequeซึ่งการใช้งาน CPython ปัจจุบันเป็นรายการบล็อกที่เชื่อมโยงสองเท่า (แต่ละบล็อกมีอาร์เรย์ของวัตถุบรรทุกสินค้า 62 ตัว) มันช่วยฟังก์ชั่นของรายการที่เชื่อมโยง นอกจากนี้คุณยังสามารถค้นหาส่วนขยาย C ที่ชื่อllistpypi หากคุณต้องการการใช้งาน 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

ตัวอย่างรายการที่เชื่อมโยงเป็นสองเท่า (บันทึกเป็น 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

ฉันยังเขียนรายการที่เชื่อมโยงเดี่ยวโดยยึดตามบทช่วยสอนบางอย่างซึ่งมีสองคลาสพื้นฐานของโหนดและรายการที่เชื่อมโยงและวิธีการเพิ่มเติมสำหรับการแทรกลบย้อนกลับเรียงลำดับและอื่น ๆ

มันไม่ใช่สิ่งที่ดีที่สุดหรือง่ายที่สุดใช้งานได้ดี

"""
🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏

Single Linked List (SLL):
A simple object-oriented implementation of Single Linked List (SLL) 
with some associated methods, such as create list, count nodes, delete nodes, and such. 

🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏
"""

class Node:
    """
    Instantiates a node
    """
    def __init__(self, value):
        """
        Node class constructor which sets the value and link of the node

        """
        self.info = value
        self.link = None

class SingleLinkedList:
    """
    Instantiates the SLL class
    """
    def __init__(self):
        """
        SLL class constructor which sets the value and link of the node

        """
        self.start = None

    def create_single_linked_list(self):
        """
        Reads values from stdin and appends them to this list and creates a SLL with integer nodes

        """
        try:
            number_of_nodes = int(input("👉   Enter a positive integer between 1-50 for the number of nodes you wish to have in the list: "))
            if number_of_nodes <= 0 or number_of_nodes > 51:
                print("💛 The number of nodes though must be an integer between 1 to 50!")
                self.create_single_linked_list()

        except Exception as e:
            print("💛 Error: ", e)
            self.create_single_linked_list()


        try:
            for _ in range(number_of_nodes):
                try:
                    data = int(input("👉   Enter an integer for the node to be inserted: "))
                    self.insert_node_at_end(data)
                except Exception as e:
                    print("💛 Error: ", e)
        except Exception as e:
            print("💛 Error: ", e)

    def count_sll_nodes(self):
        """
        Counts the nodes of the linked list

        """
        try:
            p = self.start
            n = 0
            while p is not None:
                n += 1
                p = p.link

            if n >= 1:
                print(f"💚 The number of nodes in the linked list is {n}")
            else:
                print(f"💛 The SLL does not have a node!")
        except Exception as e: 
            print("💛 Error: ", e)

    def search_sll_nodes(self, x):
        """
        Searches the x integer in the linked list
        """
        try:
            position =  1
            p = self.start
            while p is not None:
                if p.info == x:
                    print(f"💚 YAAAY! We found {x} at position {position}")
                    return True

                #Increment the position
                position += 1 
                #Assign the next node to the current node
                p = p.link
            else:
                print(f"💔 Sorry! We couldn't find {x} at any position. Maybe, you might want to use option 9 and try again later!")
                return False
        except Exception as e:
            print("💛 Error: ", e)

    def display_sll(self):
        """
        Displays the list
        """
        try:
            if self.start is None:
                print("💛 Single linked list is empty!")
                return

            display_sll = "💚 Single linked list nodes are: "
            p = self.start
            while p is not None:
                display_sll += str(p.info) + "\t"
                p = p.link

            print(display_sll)

        except Exception as e:
            print("💛 Error: ", e) 

    def insert_node_in_beginning(self, data):
        """
        Inserts an integer in the beginning of the linked list

        """
        try:
            temp = Node(data)
            temp.link = self.start
            self.start = temp
        except Exception as e:
            print("💛 Error: ", e)

    def insert_node_at_end(self, data):
        """
        Inserts an integer at the end of the linked list

        """
        try:            
            temp = Node(data)
            if self.start is None:
                self.start = temp
                return

            p = self.start  
            while p.link is not None:
                p = p.link
            p.link = temp
        except Exception as e:
            print("💛 Error: ", e)


    def insert_node_after_another(self, data, x):
        """
        Inserts an integer after the x node

        """
        try:
            p = self.start

            while p is not None:
                if p.info == x:
                    break
                p = p.link

            if p is None:
                print(f"💔 Sorry! {x} is not in the list.")
            else:
                temp = Node(data)
                temp.link = p.link
                p.link = temp
        except Exception as e: 
            print("💛 Error: ", e)


    def insert_node_before_another(self, data, x):
        """
        Inserts an integer before the x node

        """

        try:

            # If list is empty
            if self.start is None:
                print("💔 Sorry! The list is empty.")
                return 
            # If x is the first node, and new node should be inserted before the first node
            if x == self.start.info:
                temp = Node(data)
                temp.link = p.link
                p.link = temp

            # Finding the reference to the prior node containing x
            p = self.start
            while p.link is not None:
                if p.link.info == x:
                    break
                p = p.link

            if p.link is not None:
                print(f"💔 Sorry! {x} is not in the list.")
            else:
                temp = Node(data)
                temp.link = p.link
                p.link = temp           

        except Exception as e:
            print("💛 Error: ", e)

    def insert_node_at_position(self, data, k):
        """
        Inserts an integer in k position of the linked list

        """
        try:
            # if we wish to insert at the first node
            if k == 1:
                temp = Node(data)
                temp.link = self.start
                self.start = temp
                return

            p = self.start
            i = 1

            while i < k-1 and p is not None:
                p = p.link
                i += 1

            if p is None:
                print(f"💛 The max position is {i}") 
            else:    
                temp = Node(data)
                temp.link = self.start
                self.start = temp

        except Exception as e:
            print("💛 Error: ", e)

    def delete_a_node(self, x):
        """
        Deletes a node of a linked list

        """
        try:
            # If list is empty
            if self.start is None:
                print("💔 Sorry! The list is empty.")
                return

            # If there is only one node
            if self.start.info == x:
                self.start = self.start.link

            # If more than one node exists
            p = self.start
            while p.link is not None:
                if p.link.info == x:
                    break   
                p = p.link

            if p.link is None:
                print(f"💔 Sorry! {x} is not in the list.")
            else:
                p.link = p.link.link

        except Exception as e:
            print("💛 Error: ", e)

    def delete_sll_first_node(self):
        """
        Deletes the first node of a linked list

        """
        try:
            if self.start is None:
                return
            self.start = self.start.link

        except Exception as e:
            print("💛 Error: ", e)


    def delete_sll_last_node(self):
        """
        Deletes the last node of a linked list

        """
        try:

            # If the list is empty
            if self.start is None:
                return

            # If there is only one node
            if self.start.link is None:
                self.start = None
                return

            # If there is more than one node    
            p = self.start

            # Increment until we find the node prior to the last node 
            while p.link.link is not None:
                p = p.link

            p.link = None   

        except Exception as e:
            print("💛 Error: ", e)


    def reverse_sll(self):
        """
        Reverses the linked list

        """

        try:

            prev = None
            p = self.start
            while p is not None:
                next = p.link
                p.link = prev
                prev = p
                p = next
            self.start = prev

        except Exception as e:
            print("💛 Error: ", e)


    def bubble_sort_sll_nodes_data(self):
        """
        Bubble sorts the linked list on integer values

        """

        try:

            # If the list is empty or there is only one node
            if self.start is None or self.start.link is None:
                print("💛 The list has no or only one node and sorting is not required.")
            end = None

            while end != self.start.link:
                p = self.start
                while p.link != end:
                    q = p.link
                    if p.info > q.info:
                        p.info, q.info = q.info, p.info
                    p = p.link
                end = p

        except Exception as e:
            print("💛 Error: ", e)


    def bubble_sort_sll(self):
        """
        Bubble sorts the linked list

        """

        try:

            # If the list is empty or there is only one node
            if self.start is None or self.start.link is None:
                print("💛 The list has no or only one node and sorting is not required.")
            end = None

            while end != self.start.link:
                r = p = self.start
                while p.link != end:
                    q = p.link
                    if p.info > q.info:
                        p.link = q.link
                        q.link = p
                    if  p != self.start:
                        r.link = q.link
                    else:
                        self.start = q
                    p, q = q, p
                    r = p
                    p = p.link
                end = p

        except Exception as e:
            print("💛 Error: ", e)


    def sll_has_cycle(self):
        """
        Tests the list for cycles using Tortoise and Hare Algorithm (Floyd's cycle detection algorithm)
        """

        try:

            if self.find_sll_cycle() is None:
                return False
            else:
                return True


        except Exception as e:
            print("💛 Error: ", e)


    def find_sll_cycle(self):
        """
        Finds cycles in the list, if any
        """

        try:

            # If there is one node or none, there is no cycle
            if self.start is None or self.start.link is None:
                return None

            # Otherwise, 
            slowR = self.start
            fastR = self.start

            while slowR is not None and fastR is not None:
                slowR = slowR.link
                fastR = fastR.link.link
                if slowR == fastR: 
                    return slowR

            return None

        except Exception as e:
            print("💛 Error: ", e)


    def remove_cycle_from_sll(self):
        """
        Removes the cycles
        """

        try:

            c = self.find_sll_cycle()

            # If there is no cycle
            if c is None:
                return

            print(f"💛 There is a cycle at node: ", c.info)

            p = c
            q = c
            len_cycles = 0
            while True:
                len_cycles += 1
                q = q.link

                if p == q:
                    break

            print(f"💛 The cycle length is {len_cycles}")

            len_rem_list = 0
            p = self.start

            while p != q:
                len_rem_list += 1
                p = p.link
                q = q.link

            print(f"💛 The number of nodes not included in the cycle is {len_rem_list}")

            length_list = len_rem_list + len_cycles

            print(f"💛 The SLL length is {length_list}")

            # This for loop goes to the end of the SLL, and set the last node to None and the cycle is removed. 
            p = self.start
            for _ in range(length_list-1):
                p = p.link
            p.link = None


        except Exception as e:
            print("💛 Error: ", e)


    def insert_cycle_in_sll(self, x):
        """
        Inserts a cycle at a node that contains x

        """

        try:

            if self.start is None:
                return False

            p = self.start
            px = None
            prev = None


            while p is not None:
                if p.info == x:
                    px = p
                prev = p
                p = p.link

            if px is not None:
                prev.link = px
            else:
                print(f"💔 Sorry! {x} is not in the list.")


        except Exception as e:
            print("💛 Error: ", e)


    def merge_using_new_list(self, list2):
        """
        Merges two already sorted SLLs by creating new lists
        """
        merge_list = SingleLinkedList()
        merge_list.start = self._merge_using_new_list(self.start, list2.start)
        return merge_list

    def _merge_using_new_list(self, p1, p2):
        """
        Private method of merge_using_new_list
        """
        if p1.info <= p2.info:
            Start_merge = Node(p1.info)
            p1 = p1.link
        else:
            Start_merge = Node(p2.info)
            p2 = p2.link            
        pM = Start_merge

        while p1 is not None and p2 is not None:
            if p1.info <= p2.info:
                pM.link = Node(p1.info)
                p1 = p1.link
            else:
                pM.link = Node(p2.info)
                p2 = p2.link
            pM = pM.link

        #If the second list is finished, yet the first list has some nodes
        while p1 is not None:
            pM.link = Node(p1.info)
            p1 = p1.link
            pM = pM.link

        #If the second list is finished, yet the first list has some nodes
        while p2 is not None:
            pM.link = Node(p2.info)
            p2 = p2.link
            pM = pM.link

        return Start_merge

    def merge_inplace(self, list2):
        """
        Merges two already sorted SLLs in place in O(1) of space
        """
        merge_list = SingleLinkedList()
        merge_list.start = self._merge_inplace(self.start, list2.start)
        return merge_list

    def _merge_inplace(self, p1, p2):
        """
        Merges two already sorted SLLs in place in O(1) of space
        """
        if p1.info <= p2.info:
            Start_merge = p1
            p1 = p1.link
        else:
            Start_merge = p2
            p2 = p2.link
        pM = Start_merge

        while p1 is not None and p2 is not None:
            if p1.info <= p2.info:
                pM.link = p1
                pM = pM.link
                p1 = p1.link
            else:
                pM.link = p2
                pM = pM.link
                p2 = p2.link

        if p1 is None:
            pM.link = p2
        else:
            pM.link = p1

        return Start_merge

    def merge_sort_sll(self):
        """
        Sorts the linked list using merge sort algorithm
        """
        self.start = self._merge_sort_recursive(self.start)


    def _merge_sort_recursive(self, list_start):
        """
        Recursively calls the merge sort algorithm for two divided lists
        """

        # If the list is empty or has only one node
        if list_start is None or list_start.link is None:
            return list_start

        # If the list has two nodes or more
        start_one = list_start
        start_two = self._divide_list(self_start)
        start_one = self._merge_sort_recursive(start_one)
        start_two = self._merge_sort_recursive(start_two)
        start_merge = self._merge_inplace(start_one, start_two)

        return start_merge

    def _divide_list(self, p):
        """
        Divides the linked list into two almost equally sized lists
        """

        # Refers to the third nodes of the list
        q = p.link.link

        while q is not None and p is not None:
            # Increments p one node at the time
            p = p.link
            # Increments q two nodes at the time
            q = q.link.link

        start_two = p.link
        p.link = None

        return start_two

    def concat_second_list_to_sll(self, list2):
        """
        Concatenates another SLL to an existing SLL
        """

        # If the second SLL has no node
        if list2.start is None:
            return

        # If the original SLL has no node
        if self.start is None:
            self.start = list2.start
            return

        # Otherwise traverse the original SLL
        p = self.start
        while p.link is not None:
            p = p.link

        # Link the last node to the first node of the second SLL
        p.link = list2.start



    def test_merge_using_new_list_and_inplace(self):
        """

        """

        LIST_ONE = SingleLinkedList()
        LIST_TWO = SingleLinkedList()

        LIST_ONE.create_single_linked_list()
        LIST_TWO.create_single_linked_list()

        print("1️⃣  The unsorted first list is: ")
        LIST_ONE.display_sll()

        print("2️⃣  The unsorted second list is: ")
        LIST_TWO.display_sll()


        LIST_ONE.bubble_sort_sll_nodes_data()
        LIST_TWO.bubble_sort_sll_nodes_data()

        print("1️⃣  The sorted first list is: ")
        LIST_ONE.display_sll()

        print("2️⃣  The sorted second list is: ")
        LIST_TWO.display_sll()

        LIST_THREE = LIST_ONE.merge_using_new_list(LIST_TWO)

        print("The merged list by creating a new list is: ")
        LIST_THREE.display_sll()


        LIST_FOUR = LIST_ONE.merge_inplace(LIST_TWO)

        print("The in-place merged list is: ")
        LIST_FOUR.display_sll()     


    def test_all_methods(self):
        """
        Tests all methods of the SLL class
        """

        OPTIONS_HELP = """
📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗
    Select a method from 1-19:                                                          
🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒
        ℹ️   (1)    👉  Create a single liked list (SLL).
        ℹ️   (2)    👉  Display the SLL.                            
        ℹ️   (3)    👉  Count the nodes of SLL. 
        ℹ️   (4)    👉  Search the SLL.
        ℹ️   (5)    👉  Insert a node at the beginning of the SLL.
        ℹ️   (6)    👉  Insert a node at the end of the SLL.
        ℹ️   (7)    👉  Insert a node after a specified node of the SLL.
        ℹ️   (8)    👉  Insert a node before a specified node of the SLL.
        ℹ️   (9)    👉  Delete the first node of SLL.
        ℹ️   (10)   👉  Delete the last node of the SLL.
        ℹ️   (11)   👉  Delete a node you wish to remove.                           
        ℹ️   (12)   👉  Reverse the SLL.
        ℹ️   (13)   👉  Bubble sort the SLL by only exchanging the integer values.  
        ℹ️   (14)   👉  Bubble sort the SLL by exchanging links.                    
        ℹ️   (15)   👉  Merge sort the SLL.
        ℹ️   (16)   👉  Insert a cycle in the SLL.
        ℹ️   (17)   👉  Detect if the SLL has a cycle.
        ℹ️   (18)   👉  Remove cycle in the SLL.
        ℹ️   (19)   👉  Test merging two bubble-sorted SLLs.
        ℹ️   (20)   👉  Concatenate a second list to the SLL. 
        ℹ️   (21)   👉  Exit.
📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗
        """


        self.create_single_linked_list()

        while True:

            print(OPTIONS_HELP)

            UI_OPTION = int(input("👉   Enter an integer for the method you wish to run using the above help: "))

            if UI_OPTION == 1:
                data = int(input("👉   Enter an integer to be inserted at the end of the list: "))
                x = int(input("👉   Enter an integer to be inserted after that: "))
                self.insert_node_after_another(data, x)
            elif UI_OPTION == 2:
                self.display_sll()
            elif UI_OPTION == 3:
                self.count_sll_nodes()
            elif UI_OPTION == 4:
                data = int(input("👉   Enter an integer to be searched: "))
                self.search_sll_nodes(data)
            elif UI_OPTION == 5:
                data = int(input("👉   Enter an integer to be inserted at the beginning: "))
                self.insert_node_in_beginning(data)
            elif UI_OPTION == 6:
                data = int(input("👉   Enter an integer to be inserted at the end: "))
                self.insert_node_at_end(data)
            elif UI_OPTION == 7:
                data = int(input("👉   Enter an integer to be inserted: "))
                x = int(input("👉   Enter an integer to be inserted before that: "))
                self.insert_node_before_another(data, x)
            elif UI_OPTION == 8:
                data = int(input("👉   Enter an integer for the node to be inserted: "))
                k = int(input("👉   Enter an integer for the position at which you wish to insert the node: "))
                self.insert_node_before_another(data, k)
            elif UI_OPTION == 9:
                self.delete_sll_first_node()
            elif UI_OPTION == 10:
                self.delete_sll_last_node()
            elif UI_OPTION == 11:
                data = int(input("👉   Enter an integer for the node you wish to remove: "))
                self.delete_a_node(data)
            elif UI_OPTION == 12:
                self.reverse_sll()
            elif UI_OPTION == 13:
                self.bubble_sort_sll_nodes_data()
            elif UI_OPTION == 14:
                self.bubble_sort_sll()
            elif UI_OPTION == 15:
                self.merge_sort_sll()
            elif UI_OPTION == 16:
                data = int(input("👉   Enter an integer at which a cycle has to be formed: "))
                self.insert_cycle_in_sll(data)
            elif UI_OPTION == 17:
                if self.sll_has_cycle():
                    print("💛 The linked list has a cycle. ")
                else:
                    print("💚 YAAAY! The linked list does not have a cycle. ")
            elif UI_OPTION == 18:
                self.remove_cycle_from_sll()
            elif UI_OPTION == 19:
                self.test_merge_using_new_list_and_inplace()
            elif UI_OPTION == 20:
                list2 = self.create_single_linked_list()
                self.concat_second_list_to_sll(list2)
            elif UI_OPTION == 21:
                break
            else:
                print("💛 Option must be an integer, between 1 to 21.")

            print()     



if __name__ == '__main__':
    # Instantiates a new SLL object
    SLL_OBJECT = SingleLinkedList()
    SLL_OBJECT.test_all_methods()

0

การขยายคำตอบของ Nick Stinemates

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

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

    def prepend_node(self, data):
        new_node = Node()
        new_node.data = data
        new_node.next = self.head
        self.head = new_node

    def append_node(self, data):
        new_node = Node()
        new_node.data = data
        current = self.head
        while current.next:
            current = current.next
        current.next = new_node

    def reverse(self):
        """ In-place reversal, modifies exiting list"""
        previous = None
        current_node = self.head

        while current_node:
            temp =  current_node.next
            current_node.next = previous
            previous = current_node
            current_node = temp
        self.head = previous

    def search(self, data):
        current_node = self.head
        try:
            while current_node.data != data:
                current_node = current_node.next
            return True
        except:
            return False

    def display(self):
        if self.head is None:
            print("Linked list is empty")
        else:
            current_node = self.head
            while current_node:
                print(current_node.data)
                current_node = current_node.next

    def list_length(self):
        list_length = 0
        current_node = self.head
        while current_node:
            list_length += 1
            current_node = current_node.next
        return list_length


def main():
    linked_list = LinkedList()

    linked_list.prepend_node(1)
    linked_list.prepend_node(2)
    linked_list.prepend_node(3)
    linked_list.append_node(24)
    linked_list.append_node(25)
    linked_list.display()
    linked_list.reverse()
    linked_list.display()
    print(linked_list.search(1))
    linked_list.reverse()
    linked_list.display()
    print("Lenght of singly linked list is: " + str(linked_list.list_length()))


if __name__ == "__main__":
    main()

-1

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

คุณตอบคำถามเก่าที่มีคำตอบที่ได้รับคำตอบแล้วและคุณไม่ได้ให้คำอธิบายใด ๆ อะไรคือสาเหตุของการโพสต์เวอร์ชันของคุณ? มันมีประโยชน์ใด ๆ มากกว่าโซลูชั่นที่นำเสนอไปแล้ว? หรือมูลค่าเพิ่มอื่น ๆ โปรดแก้ไขคำตอบของคุณและเพิ่มคำอธิบายเพื่อทำให้คำตอบของคุณสมบูรณ์ยิ่งขึ้น
honk

-1

รายการที่เชื่อมโยงคู่ของฉันอาจเป็นที่เข้าใจได้ง่ายสำหรับ 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()

แม้ว่าจะสามารถเพิ่มความเรียบง่ายอื่น ๆ อีกมากมายในรหัสนี้ แต่ฉันคิดว่าการใช้งานแบบดิบจะช่วยให้ฉันสามารถคว้าได้มากขึ้น


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.