2018-10-02 23:42:34 +08:00
|
|
|
|
package linkedlist;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 1)单链表的插入、删除、查找操作;
|
|
|
|
|
* 2)链表中存储的是int类型的数据;
|
|
|
|
|
*
|
|
|
|
|
* Author:Zheng
|
|
|
|
|
*/
|
|
|
|
|
public class SinglyLinkedList {
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
private Node head = null;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public Node findByValue(int value) {
|
|
|
|
|
Node p = head;
|
|
|
|
|
while (p != null && p.data != value) {
|
|
|
|
|
p = p.next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return p;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public Node findByIndex(int index) {
|
|
|
|
|
Node p = head;
|
|
|
|
|
int pos = 0;
|
|
|
|
|
while (p != null && pos != index) {
|
|
|
|
|
p = p.next;
|
|
|
|
|
++pos;
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
return p;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
//无头结点
|
|
|
|
|
//表头部插入
|
|
|
|
|
//这种操作将于输入的顺序相反,逆序
|
|
|
|
|
public void insertToHead(int value) {
|
|
|
|
|
Node newNode = new Node(value, null);
|
|
|
|
|
insertToHead(newNode);
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public void insertToHead(Node newNode) {
|
|
|
|
|
if (head == null) {
|
|
|
|
|
head = newNode;
|
|
|
|
|
} else {
|
|
|
|
|
newNode.next = head;
|
|
|
|
|
head = newNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
//顺序插入
|
|
|
|
|
//链表尾部插入
|
|
|
|
|
public void insertTail(int value){
|
|
|
|
|
|
|
|
|
|
Node newNode = new Node(value, null);
|
|
|
|
|
//空链表,可以插入新节点作为head,也可以不操作
|
|
|
|
|
if (head == null){
|
|
|
|
|
head = newNode;
|
|
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
Node q = head;
|
|
|
|
|
while(q.next != null){
|
|
|
|
|
q = q.next;
|
|
|
|
|
}
|
|
|
|
|
newNode.next = q.next;
|
|
|
|
|
q.next = newNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void insertAfter(Node p, int value) {
|
|
|
|
|
Node newNode = new Node(value, null);
|
|
|
|
|
insertAfter(p, newNode);
|
2018-10-02 23:42:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public void insertAfter(Node p, Node newNode) {
|
|
|
|
|
if (p == null) return;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
newNode.next = p.next;
|
|
|
|
|
p.next = newNode;
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public void insertBefore(Node p, int value) {
|
|
|
|
|
Node newNode = new Node(value, null);
|
|
|
|
|
insertBefore(p, newNode);
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public void insertBefore(Node p, Node newNode) {
|
|
|
|
|
if (p == null) return;
|
|
|
|
|
if (head == p) {
|
|
|
|
|
insertToHead(newNode);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
Node q = head;
|
|
|
|
|
while (q != null && q.next != p) {
|
|
|
|
|
q = q.next;
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
if (q == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newNode.next = p;
|
|
|
|
|
q.next = newNode;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public void deleteByNode(Node p) {
|
|
|
|
|
if (p == null || head == null) return;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
if (p == head) {
|
|
|
|
|
head = head.next;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
Node q = head;
|
|
|
|
|
while (q != null && q.next != p) {
|
|
|
|
|
q = q.next;
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
if (q == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
q.next = q.next.next;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public void deleteByValue(int value) {
|
|
|
|
|
if (head == null) return;
|
|
|
|
|
|
|
|
|
|
Node p = head;
|
|
|
|
|
Node q = null;
|
|
|
|
|
while (p != null && p.data != value) {
|
|
|
|
|
q = p;
|
|
|
|
|
p = p.next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p == null) return;
|
|
|
|
|
|
|
|
|
|
if (q == null) {
|
|
|
|
|
head = head.next;
|
|
|
|
|
} else {
|
|
|
|
|
q.next = q.next.next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 可重复删除指定value的代码
|
|
|
|
|
/*
|
|
|
|
|
if (head != null && head.data == value) {
|
|
|
|
|
head = head.next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Node pNode = head;
|
|
|
|
|
while (pNode != null) {
|
|
|
|
|
if (pNode.next.data == data) {
|
|
|
|
|
pNode.next = pNode.next.next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
pNode = pNode.next;
|
|
|
|
|
}
|
|
|
|
|
*/
|
2018-10-02 23:42:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public void printAll() {
|
|
|
|
|
Node p = head;
|
|
|
|
|
while (p != null) {
|
|
|
|
|
System.out.print(p.data + " ");
|
|
|
|
|
p = p.next;
|
|
|
|
|
}
|
|
|
|
|
System.out.println();
|
2018-10-02 23:42:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
//判断true or false
|
|
|
|
|
public boolean TFResult(Node left, Node right){
|
|
|
|
|
Node l = left;
|
|
|
|
|
Node r = right;
|
|
|
|
|
|
|
|
|
|
System.out.println("left_:"+l.data);
|
|
|
|
|
System.out.println("right_:"+r.data);
|
|
|
|
|
while(l != null && r != null){
|
|
|
|
|
if (l.data == r.data){
|
|
|
|
|
l = l.next;
|
|
|
|
|
r = r.next;
|
|
|
|
|
continue;
|
|
|
|
|
}else{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.println("什么结果");
|
|
|
|
|
if (l==null && r==null){
|
|
|
|
|
System.out.println("什么结果");
|
|
|
|
|
return true;
|
|
|
|
|
}else{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 判断是否为回文
|
|
|
|
|
|
|
|
|
|
public boolean palindrome(){
|
|
|
|
|
if (head == null){
|
|
|
|
|
return false;
|
|
|
|
|
}else{
|
|
|
|
|
System.out.println("开始执行找到中间节点");
|
|
|
|
|
Node p = head;
|
|
|
|
|
Node q = head;
|
|
|
|
|
if (p.next == null){
|
|
|
|
|
System.out.println("只有一个元素");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
while( q.next != null && q.next.next != null){
|
|
|
|
|
p = p.next;
|
|
|
|
|
q = q.next.next;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.println("中间节点" + p.data);
|
|
|
|
|
System.out.println("开始执行奇数节点的回文判断");
|
|
|
|
|
Node leftLink = null;
|
|
|
|
|
Node rightLink = null;
|
|
|
|
|
if(q.next == null){
|
|
|
|
|
// p 一定为整个链表的中点,且节点数目为奇数
|
2018-11-18 17:17:26 +08:00
|
|
|
|
rightLink = p.next;
|
|
|
|
|
leftLink = inverseLinkList(p).next;
|
2018-11-06 23:35:10 +08:00
|
|
|
|
System.out.println("左边第一个节点"+leftLink.data);
|
2018-11-18 17:17:26 +08:00
|
|
|
|
System.out.println("右边第一个节点"+rightLink.data);
|
2018-11-06 23:35:10 +08:00
|
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
//p q 均为中点
|
2018-11-18 17:17:26 +08:00
|
|
|
|
rightLink = p.next;
|
2018-11-06 23:35:10 +08:00
|
|
|
|
leftLink = inverseLinkList(p);
|
|
|
|
|
}
|
|
|
|
|
return TFResult(leftLink, rightLink);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
//带结点的链表翻转
|
|
|
|
|
public Node inverseLinkList_head(Node p){
|
|
|
|
|
// Head 为新建的一个头结点
|
|
|
|
|
Node Head = new Node(9999,null);
|
|
|
|
|
// p 为原来整个链表的头结点,现在Head指向 整个链表
|
|
|
|
|
Head.next = p;
|
|
|
|
|
/*
|
|
|
|
|
带头结点的链表翻转等价于
|
|
|
|
|
从第二个元素开始重新头插法建立链表
|
|
|
|
|
*/
|
|
|
|
|
Node Cur = p.next;
|
|
|
|
|
p.next = null;
|
|
|
|
|
Node next = null;
|
|
|
|
|
|
|
|
|
|
while(Cur != null){
|
|
|
|
|
next = Cur.next;
|
|
|
|
|
Cur.next = Head.next;
|
|
|
|
|
Head.next = Cur;
|
|
|
|
|
System.out.println("first " + Head.data);
|
|
|
|
|
|
|
|
|
|
Cur = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回左半部分的中点之前的那个节点
|
|
|
|
|
// 从此处开始同步像两边比较
|
|
|
|
|
return Head;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
//无头结点的链表翻转
|
|
|
|
|
public Node inverseLinkList(Node p){
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
Node pre = null;
|
|
|
|
|
Node r = head;
|
|
|
|
|
System.out.println("z---" + r.data);
|
|
|
|
|
Node next= null;
|
|
|
|
|
while(r !=p){
|
|
|
|
|
next = r.next;
|
2018-10-06 23:06:09 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
r.next = pre;
|
|
|
|
|
pre = r;
|
|
|
|
|
r = next;
|
|
|
|
|
}
|
2018-10-06 23:06:09 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
r.next = pre;
|
|
|
|
|
// 返回左半部分的中点之前的那个节点
|
|
|
|
|
// 从此处开始同步像两边比较
|
|
|
|
|
return r;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
|
|
|
|
}
|
2018-11-06 23:35:10 +08:00
|
|
|
|
|
|
|
|
|
public static Node createNode(int value) {
|
|
|
|
|
return new Node(value, null);
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public static class Node {
|
|
|
|
|
private int data;
|
|
|
|
|
private Node next;
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public Node(int data, Node next) {
|
|
|
|
|
this.data = data;
|
|
|
|
|
this.next = next;
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public int getData() {
|
|
|
|
|
return data;
|
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
}
|
2018-11-06 23:35:10 +08:00
|
|
|
|
public static void main(String[]args){
|
|
|
|
|
|
|
|
|
|
SinglyLinkedList link = new SinglyLinkedList();
|
|
|
|
|
System.out.println("hello");
|
|
|
|
|
//int data[] = {1};
|
2018-11-18 17:17:26 +08:00
|
|
|
|
//int data[] = {1,2};
|
2018-11-06 23:35:10 +08:00
|
|
|
|
//int data[] = {1,2,3,1};
|
2018-11-18 17:17:26 +08:00
|
|
|
|
//int data[] = {1,2,5};
|
2018-11-06 23:35:10 +08:00
|
|
|
|
//int data[] = {1,2,2,1};
|
2018-11-18 17:17:26 +08:00
|
|
|
|
// int data[] = {1,2,5,2,1};
|
|
|
|
|
int data[] = {1,2,5,3,1};
|
2018-11-06 23:35:10 +08:00
|
|
|
|
|
|
|
|
|
for(int i =0; i < data.length; i++){
|
|
|
|
|
//link.insertToHead(data[i]);
|
|
|
|
|
link.insertTail(data[i]);
|
|
|
|
|
}
|
2018-11-18 17:17:26 +08:00
|
|
|
|
// link.printAll();
|
|
|
|
|
// Node p = link.inverseLinkList_head(link.head);
|
|
|
|
|
// while(p != null){
|
|
|
|
|
// System.out.println("aa"+p.data);
|
|
|
|
|
// p = p.next;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
System.out.println("打印原始:");
|
2018-11-06 23:35:10 +08:00
|
|
|
|
link.printAll();
|
2018-11-18 17:17:26 +08:00
|
|
|
|
if (link.palindrome()){
|
|
|
|
|
System.out.println("回文");
|
|
|
|
|
}else{
|
|
|
|
|
System.out.println("不是回文");
|
2018-11-06 23:35:10 +08:00
|
|
|
|
}
|
2018-10-02 23:42:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|