#!usr/bin/python
# -*- coding: utf-8 -*-
# 单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。单链表是一种链式存取的数据
# 结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针
# (指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。它的每个节点包含两个域,一个信息域(元素域)
# 和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
#
# 链式存储结构的线性表将采用一组任意的存储单元存放线性表中的数据元素。由于不需要按顺序存储,链表在插入、删除数据元素时比顺序存储要
# 快,但是在查找一个节点时则要比顺序存储要慢,使用链式存储可以克服顺序线性表需要预先知道数据大小的缺点,链表结构可以充分利用内存空
# 间,实现灵活的内存动态管理。但是链式存储失去了数组随机存取的特点,同时增加了节点的指针域,空间开销较大。
class Node:
    def __init__(self, val):
        self.val = val
        self.next = None


'''
单链表的基本操作:
 1、验证链表里面有没有值!
 2、从头部插入数值!
 3、从尾部插入数值!
 4、按指定位置插入数值!
 5、根据索引删除操作!
 6、查找一个值是否在链表中!
 7、按下标查找节点处的数值!
 8、给链表排序!
 9、根据下标修改节点的值!
 10.翻转链表
'''


class SingleLinkList:
    def __init__(self, head):
        self.head = head

    def is_empty(self):
        if self.head == None:
            return True
        else:
            return False

    def add(self, item):
        item.next = self.head
        self.head = item

    def add_end(self, item):
        current_node = self.head
        # 头结点不存在
        if current_node is None:
            self.head = item  # 头结点就是将要插入的节点
        else:
            # 只要当前节点的下一个节点不是None,就移动当前节点到下一个节点
            while current_node.next is not None:
                current_node = current_node.next
                print(current_node.val)
            # 跳出循环时,当前节点就是最末尾节点,将它的next指向item
            current_node.next = item

    def size(self):
        # 空链表
        if self.head is None:
            return 0
        # 链表只有一个元素
        if self.head.next is None:
            return 1
        # 链表不止一个元素
        count = 0
        current_node = self.head
        while current_node.next is not None:
            count += 1
            current_node = current_node.next
        count += 1  # 最后一个元素没有next,需要再加1
        return count

    def insert(self, index, item):
        # 索引值小于0或大于链表长度
        if index < 0 or index > self.size():
            print("插入失败,索引错误!")
        # 索引为0,头插入
        elif index == 0:
            self.add(item)
        # 索引为链表长度-1,尾插法
        elif index == self.size() - 1:
            self.add_end(item)
        # 索引为中间值
        elif index > 0:
            print("======")
            cur_index = 0
            cur_node = self.head
            while cur_node.next:
                cur_index += 1
                print(cur_index)
                if index == cur_index:  # 当前索引值等于要插入的索引值
                    item.next = cur_node.next  # 将要插入元素的next指向下一个元素
                    cur_node.next = item  # 当前元素指向要插入的元素
                    break  # 跳出循环

    def travle(self):
        # 链表为空
        if self.head is None:
            print("当前链表为空")
        # 链表只有一个元素
        elif self.head.next is None:
            print(self.head.val)
        else:
            # 链表不止一个元素
            cur_node = self.head
            while cur_node.next is not None:
                print(cur_node.val)
                cur_node = cur_node.next
            print(cur_node.val)

    def reverse_link(self):
        if self.head is None:
            return '链表为空,不可翻转'
        elif self.head.next is None:
            return self.head
        else:
            # 定义第一个节点为头结点,头节点的下一个节点为next_node,初始化头结点的next指向None
            # 1》2》3
            cur_node = self.head
            next_node = self.head.next
            cur_node.next = None
            # None <1 2>3
            while next_node:
                # 临时变量记录当前节点的下一个节点的next指向元素,否则一旦变化就无法找到了
                # None <1 2>3  tmp为3节点
                tmp = next_node.next
                # None <1 <2 3
                next_node.next = cur_node
                # 移动指针到第二个节点
                cur_node = next_node
                # 移动next_node指向tmp
                next_node = tmp
            return cur_node

    def remove_by_index(self, index):
        # 索引值不在范围内
        if index < 0 or index > self.size() - 1:
            return '索引错误'
        else:
            # 删除的是第一个元素
            if index == 0:
                self.head = self.head.next
            else:
                pre_node = None
                cur_node = self.head
                cur_index = 0
                while cur_node:
                    if cur_index != index:
                        # 移动指针pre_node和cur_node向后移动,同时索引值加1
                        pre_node = cur_node
                        cur_node = cur_node.next
                        cur_index += 1
                    else:
                        pre_node.next = cur_node.next
                        break
            return self.head

    def is_in_link(self, val):
        pass


node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node1.next = node2
node2.next = node3
l = SingleLinkList(node1)
print("打印链表长度", l.size())
print("第一次遍历")
l.travle()
l.insert(0, Node(5))
print("插入元素后遍历")
l.travle()
# print("翻转链表")
# p = SingleLinkList(l.reverse_link())
# print("翻转后链表")
# p.travle()
print("根据索引删除")
# print(l.remove_by_index(1).val)
c = SingleLinkList(l.remove_by_index(1))
c.travle()