單向鏈表

每個結點有兩個域,左邊部份叫值域,用於存放用戶數據。右邊叫指針域,存儲着指向後面一個節點的指針。
head節點永遠指向第一個節點。
tail節點永遠指向最後一個節點。node

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

    def __str__(self):
        return '<node: {} -> next: {}>'.format(self.item, self.next.item if self.next else None)

    def __repr__(self):
        return str(self.item)

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

    def append(self, item):
        node = Node(item)
        if self.head is None:
            self.head = node
            self.tail = node
        else:
            self.tail.next = node
            self.tail = node
        self.size += 1
        return self

    def index(self, item):
        for i, node in enumerate(self):
            if item == node.item:
                return i
        else:
            raise ValueError('item does not exist')

    def insert(self, index, item):
        if index < 0:
            raise IndexError

        # 若是找到就將current指向對應位置的節點,繼續後面的操做
        # 若是沒有找到(鏈表爲空或者索引超界),則追加並當即返回,後面的操做將不會執行
        for i, node in enumerate(self):
            if i == index and node is not self.tail:
                current = node
                break
        else:
            self.append(item)
            return

        node = Node(item)
        next = current.next

        # 從頭部插入
        if current is self.head:
            node.next = current
            self.head = node
        # 從中間插入(尾部插入即追加,上面已經實現)
        else:
            prev = self.head
            while prev.next is not current:
                prev = prev.next
            prev.next = node
            node.next = current

        self.size += 1

    def pop(self):
        # 若是頭部或尾部爲空,則表示鏈表爲空
        if self.head is None:
            raise Exception('empty')

        node = self.tail
        item = node.item

        # 若是頭節點沒有後節點,則表示鏈表只有一個元素
        if self.head.next is None:
            self.head = None
            self.tail = None
        # 剩下就是有多個節點的狀況
        else:
            prev = self.head
            while prev.next is not node:
                prev = prev.next
            prev.next = None
            self.tail = prev

        self.size -= 1
        return item

    def remove(self, index):
        if index < 0:
            raise IndexError('does not support negative index')

        # 若是鏈表爲空,則拋出異常
        if self.head is None:
            raise Exception('empty')

        # 若是找到就將current指向對應位置的節點,繼續後面的操做
        # 若是沒有找到(鏈表爲空或者索引超界),則拋出異常
        for i, node in enumerate(self):
            if i == index:
                current = node
                break
        else:
            raise IndexError('index out of range')

        next = current.next

        # 若是current沒有前節點也沒有後節點,表示只有一個節點
        if self.head.next is None:
            self.head = None
            self.tail = None
        # 若是不止一個節點,且current是head
        elif current is self.head:
            self.head = next
        # 若是不止一個節點、current不是head,且current是tail
        elif current is self.tail:
            self.pop()
        # 剩下就是多節點從中間remove的狀況
        else:
            prev = self.head
            while prev.next is not current:
                prev = prev.next
            prev.next = next

        self.size -= 1

    def clear(self):
        self.head = None
        self.tail = None
        self.size = 0

    def __iter__(self):
        current = self.head
        while current:
            yield current
            current = current.next

    def __len__(self):
        # current = self.head
        # count = 0
        # while current:
        #     count += 1
        #     current = current.next
        # return count
        return self.size

    def __getitem__(self, key):
        for i, node in enumerate(self):
            if key == i:
                return node
        else:
            raise IndexError('index out of range')

    def __setitem__(self, key, value):
        # for i, node in enumerate(self):
        #     if key == i:
        #         node.item = value
        # else:
        #     self.append(value)
        self[key].item = value


linklist = LinkedList()

# 測試append()
for i in range(10):
    linklist.append(i)

# 測試__iter__
for node in linklist:
    print(node)

# 測試__len__
print(len(linklist))

# 測試index()
print(linklist.index(3))
# print(linklist.index(13))

# 測試__getitem__
print(linklist[3])
# print(linklist[13])

# 測試__setitem__
linklist[5] = 15
print(list(linklist))

# 測試insert()
linklist.insert(1, 10)
print(list(linklist))
linklist.insert(0, 0)
print(list(linklist))

# 測試pop()
print(linklist.pop())

# 測試remove()
linklist.remove(0)
linklist.remove(3)
print(list(linklist))

# 測試clear()
linklist.clear()
print(list(linklist))
print(len(linklist))
相關文章
相關標籤/搜索