import java.util.Stack;
/*
* yy
* 1:单链表的插入从头开始进行插入
* 2:查询某个元素
* 3:删除某个元素
* 4:查找单链表的中间结点快速的方法
* 5:将单链表逆转
* 6:将链表倒置输出
* 7:单链表的长度是多少
* 8:合并两个有序的单链表head1和head2,循环
* 9:判断一个单链表中是否有环
* 10:找到环的入口点
* 11:带环链表的长度
* 12:如何知道环的长度
* */
//单链表的节点
class Node<T extends Comparable<T>> implements Comparable<Node<T>>{
private T data;
private Node<T> next;
public Node(){
}
public Node(T data){
this.data=data;
this.next=null;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
return true;
}
@Override
public int compareTo(Node<T> o) {
return this.data.compareTo(o.getData());
}
}
/*
* 这个单链表是没有哨兵的
* 在下一个版本中我会加入哨兵
* */
public class SingleList<T extends Comparable<T>> {
private Node<T> head;
public SingleList(){
head=null;
}
public Node<T> getHead() {
return head;
}
//单链表的插入从头开始进行插入
public void insertData(T data){
Node<T> node=new Node<T>(data);
if(this.head==null){
this.head=node;
}else{
node.setNext(head);
head=node;
}
}
//查询某个元素
public Node<T> search(T data){
Node<T> result=this.search(this.head, new Node(data));
return result==null?null:result;
}
private Node<T> search(Node<T> head,Node<T> element){
Node<T> node=head;
while(node!=null){
if(node.equals(element)){
return node;
}
node=node.getNext();
}
return null;
}
/*
* 删除某个元素
* 如果存在则返回true 否则返回false
* */
public boolean deleteData(T data){
return this.deleteData(this.head, new Node<T>(data));
}
private boolean deleteData(Node<T> head,Node<T> element){
Node<T> node=head;
Node<T> pre=null;
while(node!=null){
if(node.equals(element)){
if(node.equals(head)){
this.head=node.getNext();
}else{
pre.setNext(node.getNext());
}
node=null;
return true;
}
pre=node;
node=node.getNext();
}
return false;
}
//查找单链表的中间结点快速的方法
/*
* 链表为空;
链表非空,但仅有一个或两个节点;可以直接返回第一个节点的元素值。
链表非空,但含有三个或三个以上的节点,可以通过定义两个指针,一个指针的跳步为2次的时候,另一个指针的跳步为1次,当跳至结尾时,另一个节点恰好在中间位置。
* */
public T getMiddleNode(){
Node<T> res=this.getMiddleNode(this.head);
return res==null?null:res.getData();
}
private Node<T> getMiddleNode(Node<T> head){
Node<T> node=head;
Node<T> halfnode=null;
if(node==null){
return null;
}else if(node.getNext()==null||node.getNext().getNext()==null){
return node;
}else{
halfnode=node;
while(node.getNext()!=null){
node=node.getNext();
if(node.getNext()!=null){
node=node.getNext();
halfnode=halfnode.getNext();
}
}
return halfnode;
}
}
//将单链表逆转
public void inverse(){
this.inverse(this.head);
}
private void inverse(Node<T> head){
Node<T> node=head.getNext();
Node<T> pnode=null;
this.head.setNext(null);
while(node!=null){
pnode=node;
node=node.getNext();
pnode.setNext(this.head);
this.head=pnode;
}
}
//将链表倒置输出
public void inverseTraverse(){
this.inverseTraverse(this.head);
}
private void inverseTraverse(Node<T> head){
Node<T> node=head;
Stack<Node<T>> stack=new Stack<Node<T>>();
while(node!=null){
stack.push(node);
node=node.getNext();
}
while(!stack.isEmpty()){
System.out.print(stack.pop().getData()+" ");
}
System.out.println();
}
//单链表的遍历
public void travense(){
travense(this.head);
}
private void travense(Node<T> head){
Node<T> node=head;
while(node!=null){
System.out.print(node.getData()+" ");
node=node.getNext();
}
}
//单链表的长度是多少
public int size(){
return size(this.head);
}
private int size(Node<T> head){
Node<T> node=head;
int count=0;
while(node!=null){
count++;
node=node.getNext();
}
return count;
}
//合并两个有序的单链表head1和head2,循环
public Node<T> mergeSortedList(Node<T> head1,Node<T> head2){
if(head1==null)return head2;
if(head2==null)return head1;
Node<T> target=null;
if(head1.getData().compareTo(head2.getData())<0){
target=head1;
head1=head1.getNext();
}else{
target=head2;
head2=head2.getNext();
}
target.setNext(null);
Node<T> mergeHead=target;//记录连接后的头指针
while(head1!=null&&head2!=null){
if(head1.getData().compareTo(head2.getData())<0){
target.setNext(head1);
head1=head1.getNext();
}else{
target.setNext(head2);
head2=head2.getNext();
}
target=target.getNext();
target.setNext(null);
}
if(head1==null){
target.setNext(head2);
}else{
target.setNext(head1);
}
return mergeHead;
}
public void mergeTraverse(Node<T> node){
this.travense(node);
}
// 判断一个单链表中是否有环: hasCycle
/*
* 设置两个指针(fast, slow),初始值都指向头,slow每次前进一步,fast每次前进二步,
* 如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。
* (当然,fast先行头到尾部为NULL,则为无环链表)
* */
public boolean hasCycle(){
return this.hasCycle(this.head);
}
private boolean hasCycle(Node<T> head){
boolean flag=false;
Node<T> slow=head;
Node<T> fast=head;
while(fast!=null&&fast.getNext()!=null){
slow=slow.getNext();
fast=fast.getNext().getNext();
if(slow.equals(fast)){
flag=true;
break;
}
}
return flag;
}
/*
* 找到环的入口点
* 假设单链表的总长度为L,头结点到环入口的距离为a,环入口到快慢指针相遇的结点距离为x,环的长度为r,
* 慢指针总共走了s步,则快指针走了2s步。
* 另外,快指针要追上慢指针的话快指针至少要在环里面转了一圈多(假设转了n圈加x的距离),得到以下关系:
s = a + x;
2s = a + nr + x;
=>a + x = nr;
=>a = nr - x;
*/
//寻找环的入口点
private Node<T> FindLoopPort(Node<T> head)
{
Node<T> slow=head,fast=head;
//得到相遇点
while(fast!=null && fast.getNext()!=null)
{
slow=slow.getNext();
fast=fast.getNext().getNext();
if(slow.equals(fast))
break;
}
if(fast==null||fast.getNext()==null)
return null; //无环
//slow指向开头,fast在相遇点
//得到入口点
slow=head;
while(!slow.equals(fast)){
slow=slow.getNext();
fast=fast.getNext();
}
return slow;
}
/*
* 如何知道环的长度
* 记录下问题1的碰撞点p,slow、fast从该点开始,再次碰撞所走过的操作数就是环的长度s。
* */
public int getCycleLength(){
return this.getCycleLength(this.head);
}
private int getCycleLength(Node<T> head){
Node<T> p=this.FindLoopPort(head);
if(p==null) return 0;//无环
Node<T> slow=p;
Node<T> fast=p;
int count=0;
while(fast!=null&& fast.getNext()!=null){
slow=slow.getNext();
fast=fast.getNext().getNext();
count++;
if(slow.equals(fast)){
break;
}
}
return count;
}
//带环链表的长度
public int getCycleListLength(){
return getCycleListLength(this.head);
}
private int getCycleListLength(Node<T> head){
Node<T> pnode=this.FindLoopPort(head);
if(pnode==null){
return this.size(head);
}
int count=0;//记录头结点到接入点的距离
Node<T> node=head;
while(!node.equals(pnode)){
count++;
node=node.getNext();
}
int count1=this.getCycleLength(head);//得到环的长度
return count+count1;
}
// 判断两个单链表是否相交
//如果单纯的判断是否相交,只需要看最后一个指针是否相等
/*
* 一共有二中解法
* 第一种:将二个链表连接起来,查看链表2是否存在环。如果存在环,则第一个入口点就是相交的点
*
* */
//单链表是没有环的
/*
* 二个链表相交的性质
* (1)一旦两个链表相交,那么两个链表中的节点一定有相同地址。
(2)一旦两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点。
* 解题思路
* 先遍历第一个链表到他的尾部,然后将尾部的next指针指向第二个链表(尾部指针的next本来指向的是null)。
* 这样两个链表就合成了一个链表,判断原来的两个链表是否相交也就转变成了判断新的链表是否有环的问题了:即判断单链表是否有环
* */
public Node<T> isIntersectByConnect(Node<T> head1,Node<T> head2){
//得到当前链表的最后一个节点
Node<T> target=null;
if(head1!=null){
while(head1.getNext()!=null){
head1=head1.getNext();
}
head1.setNext(head2);
target=head1;
}else if(head2!=null){
while(head2.getNext()!=null){
head2=head2.getNext();
}
head2.setNext(head1);
target=head2;
}
return this.FindLoopPort(head2);
}
public Node<T> isIntersect(Node<T> head1,Node<T> head2){
Node<T> target=null;
if(head1==null||head2==null)return target;
boolean pos1=this.hasCycle(head1);
boolean pos2=this.hasCycle(head2);
// 一个链表有环,另一个链表没环,那肯定没有交点
if(pos1==false&&pos2==true||pos1==false&&pos2==true)return null;
int len1=this.size(head1);
int len2=this.size(head2);
if(len1>=len2){
for(int i=0;i<len1-len2;i++){
head1=head1.getNext();
}
}else{
for(int i=0;i<len2-len1;i++){
head2=head2.getNext();
}
}
while(head1!=null&&head2!=null){
if(head1.equals(head2)){
target=head1;
break;
}
else{
head1=head1.getNext();
head2=head2.getNext();
}
}
return target;
}
}
package singleList;
public class TestSingleList {
/**
* yy
* @param args
*/
public static void main(String[] args) {
SingleList<String> list=new SingleList<String>();
SingleList<String> list1=new SingleList<String>();
list.insertData("a");
list.insertData("b");
list.insertData("c");
list.insertData("d");
list.insertData("f");
list.insertData("g");
list.travense();
System.out.println();
System.out.println(list.size());
System.out.println(list.search("6"));
System.out.println(list.deleteData("a"));
list.travense();
System.out.println(list.size());
list.inverse();
list.travense();
System.out.println();
System.out.println(list.getMiddleNode());
list.inverseTraverse();
list1.insertData("m");
list1.insertData("a");
// list.mergeTraverse(list.mergeSortedList(list.getHead(), list1.getHead()));
System.out.println(list.hasCycle());
}
}