package list;
public class MyList {
Node head;
/**
* 向链表的尾部添加数据
* @param data
*/
public void add(int data) {
Node node = new Node(data);
if(head == null) {
head = node;
}else {
// 遍历链表,找到链表的尾部
Node temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = node;
}
}
/**
* 删除指定索引上的数据
* @param index
*/
public boolean deleteByIndex(int index) {
if(head == null || index<0 ) {
return false;
}
if(index == 0) {
head = head.next;
return true;
}
// 定义两个指针,一个记录现在走的位置,一个记录上一次走的位置,由于是单向链表,所以需要记住上一次走的位置
Node pre = head;
Node cur = head.next;
// 定义book是为了去找到index,因为传入进来的是索引值,链表无法通过下标索引去查找,所以只能通过这种方式去查找
int book = 1;
while(cur != null) {
if(book == index) {
pre.next = cur.next;
return true;
}
book++;
pre = cur;
cur = cur.next;
}
return false;
}
/**
* 删除指定数据
* @param element
* @return
*/
public boolean deleteByData(int data) {
if(head == null) {
return false;
}
if(head.data == data) {
head = head.next;
return true;
}
Node pre = head;
Node cur = head.next;
while(cur != null) {
if(cur.data == data) {
pre.next = cur.next;
return true;
}
pre = cur;
cur = cur.next;
}
// 到这里出了while循环,一定是cur==null,并且一路上还没有找到和cur.data相等的element,说明这个元素不存在,删除失败
return false;
}
/**
* 在指定的位置插入节点
* @param index
* @param data
*/
public boolean insert(int index, int data) {
// 支持在链表的末尾插入输入,但不支持在头部插入之前插入
if(index<0 || index>=this.length()+1) {
return false;
}
Node temp = head;
for(int i = 1; i<index; i++) {
// 要在index索引处插入元素,先要找到index-1索引处的元素。注意这里i从1开始,因为当第一次进入循环的时候temp已经在第1索引位置了,而不是第0索引位置
temp = temp.next;
}
// 出了for循环的时候,temp正好是在index-1的位置处
Node node = new Node(data);
node.next = temp.next;
temp.next = node;
return true;
}
/**
* 链表长度
* @return
*/
public int length() {
if(head == null) {
return 0;
}
// 计数器
int count = 0;
Node temp = head;
while(temp != null) {
temp = temp.next;
count++;
}
return count;
}
/**
* 排序
*/
public void sort() {
if(head == null) {
return;
}
Node i = head;
Node j = null;
while(i != null) {
j = i.next;
// j指针从前走到后,把每一个j指向的节点和i指向的节点对比,每一轮循环结束以后,最小值都来到了最前面
while(j != null) {
if(i.data > j.data) {
int temp = i.data;
i.data = j.data;
j.data = temp;
}
j = j.next;
}
// 内层循环结束以后,说明最小的数已经排好了,这时候要处理下一个节点了
i = i.next;
}
}
/**
* 反向打印链表,注意:只是反向打印,不是反转
* @param head
*/
public void printReverse(Node node) {
if(node == null) {
return;
}
// 递归
printReverse(node.next);
System.out.print(node.data + " ");
}
/**
* 反转链表
*/
public void reverseList() {
Node pre = null;
Node cur = head;
while(cur != null) {
Node nextNdoe = cur.next;
// 反转指针
cur.next = pre;
// 让pre来到cur的位置
pre = cur;
// 让cur来到nextNode的位置
cur = nextNdoe;
}
// 全部反转完了以后设置头结点
this.head = pre;
}
/**
* 寻找链表的中间节点
* @return
*/
public Node searchMiddleNode() {
if(head == null) {
return null;
}
// 定义两个指针,都从头结点开始一起往后走,一个一次走两步,一个一次走一步
Node slow = head;
Node fast = head;
// 当快指针指向链表的末尾的时候,慢指针刚好指向中间节点
while(fast != null && fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
/**
* 打印链表
*/
public void print() {
if(head == null) {
return;
}
Node temp = head;
while(temp != null) {
System.out.print(temp.data + " ");
temp = temp.next;
}
}
}
class Node{
int data;
Node next;
public Node(int data) {
this.data = data;
}
}