Python实现单链表

242 阅读3分钟
"""
 @Time    : 2019/1/9 16:05
 @File    : LinkList.py
"""

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


class LinkList(object):
    def __init__(self):
        self.head = None

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

    def len_list(self):
        i = 0
        node = self.head
        while node:
            i += 1
            node = node.next
        return i

    #开头添加元素
    def prepend_list(self, item):
        node = Node(item)
        next_node = self.head
        self.head = node
        node.next = next_node

    # 末尾添加元素
    def append_list(self, item):
        node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            p = self.head
            while p.next:
                p = p.next
            p.next = node

    # 打印链表
    def print_list(self):
        node = self.head
        # print(type(node))
        list = []
        while node:
            list.append(node.data)
            node = node.next
        print(list)

    # 插入元素
    def insert_list(self, index, item):
        len = self.len_list()
        if index < 0:
            print("ERROR!")
        if len == 0:
            print('LinkList is Empty!')
        if index == 0:
            self.prepend_list(item)
        elif index >= len:
            self.append_list(item)
        else:
            i = 0
            node = Node(item)
            next_node = self.head
            # 下面几行每次循环都要进行if判断,时间复杂度高
            # while next_node:
            #     if index == i+1:
            #         p = next_node.next
            #         next_node.next = node
            #         node.next = p
            #         break
            #     i += 1
            #     next_node = next_node.next
            while i+1 < index:
                i += 1
                next_node = next_node.next
            p = next_node.next
            next_node.next = node
            node.next = p

    # 删除表中第一个元素
    def del_first(self):
        if self.is_empty():
            print("LinkList is Empty!")
        fist_node = self.head
        second_node = fist_node.next
        self.head = second_node

    # 删除表中最后一个元素
    def del_last(self):
        if self.is_empty():
            print("LinkList is Empty!")
        node = self.head
        # 下面几行每次循环都要进行if判断,时间复杂度高
        # while node:
        #     if node.next.next is None:
        #         node.next = None
        #     node = node.next
        len = self.len_list()
        i = 0
        while i < len-2:
            i += 1
            node = node.next
        node.next = None

    # 删除指定位置的元素
    def del_index(self, index):
        if self.is_empty():
            print("LinkList is Empty!")
        len = self.len_list()
        if index < 0:
            print("ERROR!")
        elif index >= len:
            print("index is larger than len of LinkList!")
        elif index == 0:
            self.del_first()
        elif index == len-1:
            self.del_last()
        else:
            i = 0
            node = self.head
            while i+1 < index:
                node = node.next
                i += 1
            node.next = node.next.next

    # 查找某一元素
    def search_list(self, item):
        node = self.head
        i = 0
        while node:
            if node.data == item:
                return i
            i += 1
            node = node.next
        return -1

    # 翻转列表
    '''
    实现方法:从一个表的首端不断取下结点,将其加入另一个表的首端,就形成了反转的过程。 时间复杂度 O(n)
    就像将一摞书一本本拿下来叠成另一摞
    '''
    def reverse_list(self):
        new_list = None
        while self.head is not None:
            node = self.head
            self.head = node.next
            node.next = new_list   # 摘下来的结点的next应该指向上一个摘下来的结点
            new_list = node        # 将摘下来的结点和之前结点 加入到 新的结点序列
        self.head = new_list       # 指向反转后的表头结点

    # 列表排序,使用插入排序
    '''
    链表的排序有两种方法:
        1. 移动每个结点之间的元素
        2. 调整结点之间的链接关系
    sort_list1 采用的是第一种
    sort_list2 采用的是第二种
    '''
    def sort_list1(self):
        """
        1. 设定扫描指针 cur_node, 从首结点的第二个结点开始。
        2. 扫描指针前面的结点序列都已经是排序好的
        3. 将扫描指针的值依次与扫描指针前面的结点序列中的值相比,如果序列中的值比扫描指针中的值大,
        则将扫描指针中的值与序列中的值替换,继续用替换后的值与序列中的值比较,由于该序列已经是排序好的,
        所以替换后的值肯定比该序列未比较的值都小,即进行一系列的替换,完成已排序序列中元素的后移。
        4. 若序列都已经比较一遍,则扫描指针下移。
        :return:
        """
        cur_node = self.head.next
        while cur_node is not None:
            cur_data = cur_node.data
            p = self.head
            # 若 已排序序列中的元素比扫描指针的元素小,则序列指针向后移动,直到p指针为扫描指针或p的data大于扫描指针的data
            while p is not cur_node and p.data <= cur_data:
                p = p.next
            # 替换大元素,完成插入
            while p is not cur_node:
                p_data = p.data
                p.data = cur_data
                cur_data = p_data
                p = p.next
            # 若进行了while p is not cur_node:这个循环,则cur_data已经插入到排序好的序列中,
            # 但排序好的序列的最后一个元素已经被倒数第二个元素的值替换,所以 cur_node.data 的值应该是新的排序好序列的最后一个元素,
            # 所以进行赋值,将排序的最后一个元素的值复制给cur_node,若放在循环里面,则每次都换替换 cur_node.data,没有必要,只需最后替换
            cur_node.data = cur_data
            cur_node = cur_node.next

    def sort_list2(self):
        last = self.head
        cur_node = last.next
        while cur_node is not None:
            p = self.head
            q = None
            while p is not cur_node and p.data <= cur_node.data:
                q = p
                p = p.next
            if p is cur_node:
                last = cur_node
            else:
                last.next = cur_node.next
                cur_node.next = p
                if q is None:
                    self.head = cur_node
                else:
                    q.next = cur_node
            cur_node = last.next

link = LinkList()
for i in range(5):
    link.append_list(i)
print(link.len_list())
link.print_list()
link.prepend_list(10)
link.print_list()
link.insert_list(3, 100)
link.print_list()
link.del_first()
link.print_list()
link.del_last()
link.print_list()
link.del_index(3)
link.print_list()
index = link.search_list(0)
print(index)
link.reverse_list()
link.print_list()
link.append_list(74)
link.append_list(20)
link.append_list(2)
link.sort_list2()
link.print_list()

参考:

  1. Python 单向链接表反转与排序
  2. “数据结构与算法(Python 语言)”教学材料