单链表练习(方便起见,使用下面这个链表)
注释部分就是练习题所在位置
public class SingleLinkedListDemo {
public static void main(String[] args) {
SingleLinkedList s1 = new SingleLinkedList();
Node n1 = new Node(1,"xiao");
Node n2 = new Node(2,"biao");
Node n3 = new Node(3,"diao");
s1.addByOrder(n1);
s1.addByOrder(n3);
s1.addByOrder(n2);
System.out.println("添加");
s1.list();
// 测试逆序打印
System.out.println("逆序打印");
reversePrint(s1.getNode());
System.out.println("逆序打印后原来链表的数据");
s1.list();
System.out.println("修改");
Node n4 = new Node(3,"Xdiao");
s1.updata(n4);
s1.list();
System.out.println("删除");
s1.del(3);
s1.list();
// 求单链表中有效节点的个数
System.out.println(getLength(s1.getNode()));
// 测试一下是否得到了倒数第k个节点
Node res = findeLastIndexNode(s1.getNode(),1);
// 测试一下单链表的反转
System.out.println("反转单链表");
reversetList(s1.getNode());
s1.list();
}
/* // 1.获取单链表的节点个数(如果是带头节点的链表,不需要统计头节点)
public static int getLength(Node head){
if (head.next == null){
return 0;
}
int length = 0;
// 辅助节点
Node temp = head.next;
while (temp != null){
length++;
temp = temp.next;// 遍历
}
return length;
}
// 2.查找单链表中倒数第k个节点
// 思路:
// 1. 编写一个方法,用来接受head节点,同时接受一个index
// 2. index 表示是倒数第index个节点
// 3. 先把链表从头到位遍历,得到链表的总的长度
// 4. 得到size后,我们从链表的第一个开始遍历(size - index)个,就可以得到
// 5. 如果找到就返回节点,否则返回空
public static Node findeLastIndexNode(Node head, int index){
// 判断为空,返回null
if (head.next == null){
return null;
}
// 第一个遍历得到链表的长度(节点个数)
int size = getLength(head);
// 第二遍遍历,size-index 位置, 就是我们倒数的第K个节点
// 先做一个index校验
if (index <= 0 || index > size){
return null;
}
// 定义一个辅助变量
Node cur = head.next;
for (int i = 0; i < size - index; i++){
cur = cur.next;
}
return cur;
}
// 3.将单链表进行反转
public static void reversetList(Node head){
// 如果当前列表为空,或者只有一个节点,无需反转,直接返回
if (head.next == null || head.next.next == null){
return;
}
// 定义一个而辅助的指针,帮助我们遍历原来的链表
Node cur = head.next;
// 指向当前节点的下一个
Node next = null;
Node reverseHead = new Node(0,"");
// 遍历原来的链表
while (cur != null){
next = cur.next; // 暂时保存当前节点的下一个
cur.next = reverseHead.next; // 将cur的下一个节点指向新的链表的头补
reverseHead.next = cur; // 将节点连接上新的链表上
cur = next; // 让cur后移
}
// 将head.next 指向 reverseHead,实现反转
head.next = reverseHead.next;
}
// 4.逆序打印链表,使用栈
public static void reversePrint(Node head){
// 判断空链表,直接返回
if (head.next == null){
return;
}
// 创建一个栈,将各个节点压入栈
Stack<Node> stack = new Stack<>();
Node cur = head.next;
// 将链表的所有节点压入栈
while (cur != null){
stack.push(cur);
cur = cur.next;
}
// 将栈中的元素出栈使用pop
while (stack.size() > 0){
System.out.println(stack.pop()); // stack的特点是先进后出
}
*/ }
}
// 定义一个SingleLinkedList
class SingleLinkedList{
// 先初始化一个头节点
private Node head = new Node(0,"");
// 获取头节点
public Node getNode(){
return head;
}
// 添加节点
public void addByOrder(Node node){
Node temp = head;
boolean flag = false; // 添加的元素是否存在
while(true){
if (temp.next == null){
break;
}
if (temp.next.no > node.no){
break;
} else if (temp.next.no == node.no){
flag = true;
break;
}
// 如果没找到最后
temp = temp.next;
}
if (flag == false){
node.next = temp.next;
temp.next = node;
}else{
System.out.println("编号存在");
}
}
// 修改链表
public void updata(Node node){
Node temp = head.next;
boolean flag = false; // 判断是否找到当前值
while (true){
if (temp == null){
break;
}
if (temp.no == node.no){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
temp.no = node.no;
temp.name = node.name;
}else {
System.out.println("不存在");
}
}
// 删除链表
public void del(int no){
Node node = head.next;
boolean flag = false;
while (true){
if (node == null){
break;
}
if (node.next.no == no){
flag = true;
break;
}
node = node.next;
}
if (flag){
node.next = node.next.next;
}else{
System.out.println("编号不存在");
}
}
// 显示链表
public void list(){
if (head.next == null){
System.out.println("链表为空");
return;
}
Node temp = head.next;
while (true){
if (temp == null){
break;
}
System.out.println(temp.toString());
temp = temp.next;
}
}
}
// 定义一个Node 对象
class Node{
public String name;
public int no;
// 指向下一个
public Node next;
public Node(int no, String name) {
this.name = name;
this.no = no;
}
@Override
public String toString() {
return "Node{" +
"name='" + name + '\'' +
", no=" + no +
'}';
}
}
获取单链表的节点个数(如果是带头节点的链表,不需要统计头节点
// 获取单链表的节点个数(如果是带头节点的链表,不需要统计头节点)
public static int getLength(Node head){
if (head.next == null){
return 0;
}
int length = 0;
// 辅助节点
Node temp = head.next;
while (temp != null){
length++;
temp = temp.next;// 遍历
}
return length;
}
获取单链表倒数第k个元素
// 2.查找单链表中倒数第k个节点
// 思路:
// 1. 编写一个方法,用来接受head节点,同时接受一个index
// 2. index 表示是倒数第index个节点
// 3. 先把链表从头到位遍历,得到链表的总的长度
// 4. 得到size后,我们从链表的第一个开始遍历(size - index)个,就可以得到
// 5. 如果找到就返回节点,否则返回空
public static Node findeLastIndexNode(Node head, int index){
// 判断为空,返回null
if (head.next == null){
return null;
}
// 第一个遍历得到链表的长度(节点个数)
int size = getLength(head);
// 第二遍遍历,size-index 位置, 就是我们倒数的第K个节点
// 先做一个index校验
if (index <= 0 || index > size){
return null;
}
// 定义一个辅助变量
Node cur = head.next;
for (int i = 0; i < size - index; i++){
cur = cur.next;
}
return cur;
}
链表的反转(腾讯面试题)
思路:
- 先去创建定义一个节点,
reverseHead = new Node()
- 从头到尾遍历原来的链表,每遍历一个节点,就将其取出,并放进新的链表
- 原来的链表的
head.next = reverseHead.next
// 将单链表进行反转
public static void reversetList(Node head){
// 如果当前列表为空,或者只有一个节点,无需反转,直接返回
if (head.next == null || head.next.next == null){
return;
}
// 定义一个而辅助的指针,帮助我们遍历原来的链表
Node cur = head.next;
// 指向当前节点的下一个
Node next = null;
Node reverseHead = new Node(0,"");
// 遍历原来的链表
while (cur != null){
next = cur.next; // 暂时保存当前节点的下一个
cur.next = reverseHead.next; // 将cur的下一个节点指向新的链表的头补
reverseHead.next = cur; // 将节点连接上新的链表上
cur = next; // 让cur后移
}
// 将head.next 指向 reverseHead,实现反转
head.next = reverseHead.next;
}
###从尾到头打印链表(百度面试)
思路:
- 上面的题是逆序打印单链表
- 方式一:先将单链表进行反转操作,然后遍历打印即可,这样的问题是会破坏原来的单链表的结构,不建议
- 方式2:可以利用栈这个数据结构,将各个节点压入栈中,然后利用栈的先进后出的特点,就实现了逆序打印
// 先简单了解下什么叫做栈
import java.util.Stack;
// 演示栈Stack的基本使用
public class TeskStack {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
// 入栈
stack.add("jack");
stack.add("tom");
stack.add("smith");
// 出栈
while (stack.size() > 0){
// pop就是Stack的将栈顶部数据取出的方法
System.out.println(stack.pop());
}
}
}
// 4.逆序打印链表,使用栈
public static void reversePrint(Node head){
// 判断空链表,直接返回
if (head.next == null){
return;
}
// 创建一个栈,将各个节点压入栈
Stack<Node> stack = new Stack<>();
Node cur = head.next;
// 将链表的所有节点压入栈
while (cur != null){
stack.push(cur);
cur = cur.next;
}
// 将栈中的元素出栈使用pop
while (stack.size() > 0){
System.out.println(stack.pop()); // stack的特点是先进后出
}
}