package linkedlist;

import java.util.Stack;

/*
* 单向链表:
* 现在明确要干什么:
* 单向链表节点类:
* 1.date域
* 2.next指针
* 3.这里给多一个int型的number类型
*
* 单向链表类:
* 1.一个头节点
* 3.增加节点的方法,直接在后面增加
*/
public class SingleLinkedList
{
public Node head=new Node("", 0);
/*
* 普通地在后面增加节点方法
*/
public void add(Node node)
{
Node temp=this.head;
while(temp.next!=null)
{
temp=temp.next;
}
temp.next=node;
}
/*
* 第二种方式添加节点时,根据number编号从小到大将节点插入到指定位置
* (如果有这个number值的时候,则添加失败,并给出提示)
* 这里是有一个flag标记是否能找到这样子的位置,
* 当存在有number号和node相等的时候flag=true,这时就不能添加
*/
public void add2(Node node)
{
Node temp=head;
boolean flag=false;
while(true)
{
//这里表示要么这个链表是空的,要么是到了链表的最后
if(temp.next==null)
break;
if(temp.next.number>node.number)
break;
if(temp.next.number==node.number)
{
flag=true;
break;
}
temp=temp.next;
}
if(flag)
{
System.out.println("这个编号已经存在");
}
else
{
node.next=temp.next;
temp.next=node;
}
}
/*
* 修改节点的信息,根据number来修改
*/
public void update(Node node)
{
Node temp=head;
boolean flag=false;
while(true)
{
//要么这个链表是空的,要么到了链表尾,都是找不到
if(temp.next==null)
break;
if(temp.next.number==node.number)
{
flag=true;
break;
}
temp=temp.next;
}
//如果找到了就干什么
if(flag)
{
temp.next.date=node.date;
}
else
System.out.println("不存在这个编号");
}
/*
* 删除节点,方法和前面的差不多
*/
public void delete(int number)
{
Node temp=head;
boolean flag=false;
while(true)
{
if(temp.next==null)
break;
if(temp.next.number==number)
{
flag=true;
break;
}
temp=temp.next;
}
if(flag)
{
temp.next=temp.next.next;
}
else
{
System.out.println("不存在这样的节点");
}
}
/*
* 遍历这个链表
*/
public void show()
{
if(head.next==null)
{
System.out.println("链表是空的");
return;
}
Node temp=head.next;
while(true)
{
if(temp==null)
{
break;
}
System.out.println(temp);
temp=temp.next;
}
}

/*
* 将单链表反转
* 就是将这个链表传进来,然后将这个链表的节点翻转过来
*/
public void reverse1(SingleLinkedList list)
{
//如果这个链表是空链表或者是长度为1的链表,就不用翻转
if(list.head.next==null||list.head.next.next==null)
{
return;
}
//确定是要翻转了,然后新建一个头节点,然后再遍历这个链表
//每一次遍历的节点就加入到新的头节点的最前面
//这里需要保存一下每一次遍历的节点的下一个节点,因为如果我们将
//遍历的节点加入到新的头节点的链表后,就无法找到当前节点的下一个节点了
Node head=new Node("", 0);
Node temp1=list.head.next;
Node tempnext;
while(temp1!=null)
{
tempnext=temp1.next;

temp1.next=head.next;
head.next=temp1;

temp1=tempnext;
}
list.head.next=head.next;
}
/*
* 说到翻转,最可能是想到栈的数据结构,它的先进后出的结构可以很轻松地实现
* 翻转地效果
*/
public void reverse2(SingleLinkedList list)
{
Stack<Node> stack=new Stack<Node>();
Node temp=list.head.next;
while(temp!=null)
{
stack.push(temp);
temp=temp.next;
}
while(stack.size()>0)
{
System.out.println(stack.pop());
}
}
/*
* 查找单链表中的倒数第k个结点
* 这里是这样子,先利用getlength的方法得到list的长度
* 然后利用长度length-index就是刚刚好是倒数index位置的节点
*/
public Node find(SingleLinkedList list,int index)
{
int length=this.getlength(list);
//我觉得应该先处理一些不用返回的情况
if(list.head.next==null||index<=0||index>length)
{
System.err.println("找不到");
return null;
}
Node temp=list.head.next;
for (int i = 0; i < length-index; i++)
{
temp=temp.next;
}
return temp;
}
/*
* 返回这个链表地长度
*/
public int getlength(SingleLinkedList list)
{
Node temp=list.head.next;
int length=0;
while(temp!=null)
{
length++;
temp=temp.next;
}
return length;
}
public static void main(String[] args)
{
Node h1 = new Node("a", 1);
Node h2 = new Node("b", 2);
Node h3 = new Node("c", 3);
Node h4 = new Node("d", 4);

//创建要给链表
SingleLinkedList singleLinkedList = new SingleLinkedList();

//加入
singleLinkedList.add2(h1);
singleLinkedList.add2(h4);
singleLinkedList.add2(h2);
singleLinkedList.add2(h3);
singleLinkedList.show();
System.out.println();
singleLinkedList.update(new Node("z", 3));
singleLinkedList.show();
System.out.println("翻转");
singleLinkedList.reverse1(singleLinkedList);
singleLinkedList.show();
System.out.println();
singleLinkedList.reverse2(singleLinkedList);
System.out.println("删除");
singleLinkedList.delete(3);
singleLinkedList.show();
System.out.println();
System.out.println(singleLinkedList.find(singleLinkedList, 0));
}
}
class Node
{
public String date;
public int number;
public Node next;
public Node(String date, int number)
{
this.date = date;
this.number = number;
}
@Override
public String toString()
{
return "Node [date=" + date + ", number=" + number + "]";
}

}