1、链表的数据结构定义
public class Node() {
private int data;
private Node next;
public Node(int data) {
this.data = data
}
}
2、添加链表节点
public void addNode(int d){
Node newNode=new Node(d);
if (head==null) { //若原链表为空,新建结点为头结点
head=newNode;
return;
}
Node tmp=head; //否则将新节点插入表尾
while(tmp.next!=null){
tmp=tmp.next;
}
tmp.next=newNode;
}
3、删除指定位置的节点
public Boolean deleteNode(int index){
if (index<1|| index>length()) { //删除元素位置不合理
return false;
}
//删除链表第一个元素
if (index==1) {
head=head.next;
return true;
}
int i=1;
Node preNode=head; //preNode指向头结点
Node curNode=preNode.next; //curNode指向头结点的下一个结点,即当前结点
while(curNode!=null){ //当前结点非空
if (i==index) {
preNode.next=curNode.next;
return true;
}
preNode=curNode;
curNode=curNode.next;
i++;
}
return true;
}
4、链表排序
public Node orderList(){ //冒泡排序~~~~~~~
Node nextNode=null;
int tmp=0;
Node curNode=head;
while(curNode.next!=null){
nextNode=curNode.next;
while(nextNode!=null){
if (curNode.data>nextNode.data) {//exchanhe
tmp=curNode.data;
curNode.data=nextNode.data;
nextNode.data=tmp;
}
nextNode=nextNode.next;
}
curNode=curNode.next;
}
return head;
}
5、合并有序链表
// 两个参数代表的是两个链表的头结点
public Node mergeLinkList(Node head1, Node head2) {
if (head1 == null && head2 == null) { // 如果两个链表都为空
return null;
}
if (head1 == null) {
return head2;
}
if (head2 == null) {
return head1;
}
Node head; // 新链表的头结点
Node current; // current结点指向新链表
// 一开始,我们让current结点指向head1和head2中较小的数据,得到head结点
if (head1.data < head2.data) {
head = head1;
current = head1;
head1 = head1.next;
} else {
head = head2;
current = head2;
head2 = head2.next;
}
while (head1 != null && head2 != null) {
if (head1.data < head2.data) {
current.next = head1; // 新链表中,current指针的下一个结点对应较小的那个数据
current = current.next; // current指针下移
head1 = head1.next;
} else {
current.next = head2;
current = current.next;
head2 = head2.next;
}
}
// 合并剩余的元素
if (head1 != null) { // 说明链表2遍历完了,是空的
current.next = head1;
}
if (head2 != null) { // 说明链表1遍历完了,是空的
current.next = head2;
}
return current ;
}
6、链表的反转
//遍历反转
public static Node reverseList(Node node) {
Node pre = null;
Node next = null;
while (node != null) {
next = node.next;
node.next = pre;
pre = node;
node = next;
}
return pre;
}
//递归反转
public Node reverse(Node head) {
if (head == null || head.next == null)
return head;
Node temp = head.next;
Node newHead = reverse(head.next);
temp.next = head;
head.next = null;
return newHead;
}
7、倒叙打印链表
//自定义栈,倒序打印
public void reversePrint(Node head) {
if (head == null) {
return;
}
Stack<Node> stack = new Stack<Node>(); //新建一个栈
Node current = head;
//将链表的所有结点压栈
while (current != null) {
stack.push(current); //将当前结点压栈
current = current.next;
}
//将栈中的结点打印输出即可
while (stack.size() > 0) {
System.out.println(stack.pop().data); //出栈操作
}
}
//递归倒序打印
public void reversePrint1(Node head) {
if (head == null) {
return;
}
reversePrint(head.next);
System.out.println(head.data);
}
8、判断链表是否有环
// 判断单链表是否有环,我们用两个指针去遍历:
// first指针每次走一步,second指针每次走两步,如果first指针和second指针相遇,说明有环。
public static boolean hasCycle(Node head) {
if (head == null) {
return false;
}
Node first = head;
Node second = head;
while (second != null) {
first = first.next; // first指针走一步
second = second.next.next; // second指针走两步
if (first == second) { // 一旦两个指针相遇,说明链表是有环的
return true;
}
}
return false;
}
9、求链表的倒数第k个节点的数据
我们定义两个指针,第一个指针从链表的头指针开始遍历向前走k-1步,第二个指针保持不动:从第k步开始,第二个指针也开始从链表的头指针开始遍历,由于两个指针的距离保持在k-1,当第一个(走在前面的)指针到达链表的尾结点时,第二个指针(走在后面的)指针正好是倒数第k个结点.。
public static Node FindKthtoTail(Node head, int k) {
if (head == null || k == 0)
return null;
Node slow = head;
Node fast = head;
for (int i = 0; i < k - 1; i++)
fast = fast.next;
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}