package LinkedList;
import java.util.Stack;
public class LinkedList {
public static void main(String[] args) {
Node node1=new Node(1,"111");
Node node2=new Node(5,"555");
Node node3=new Node(8,"888");
Node node4=new Node(10,"101010");
SingleLinkedList linkedList=new SingleLinkedList();
linkedList.addNode(node1);
linkedList.addNode(node2);
linkedList.addNode(node3);
linkedList.addNode(node4);
System.out.println("第一个链表:");
linkedList.showList(linkedList.head);
Node node5=new Node(3,"333");
Node node6=new Node(4,"444");
Node node7=new Node(6,"666");
Node node8=new Node(12,"121212");
SingleLinkedList linkedList1=new SingleLinkedList();
linkedList1.addNode(node5);
linkedList1.addNode(node6);
linkedList1.addNode(node7);
linkedList1.addNode(node8);
System.out.println("第二个链表:");
linkedList1.showList(linkedList1.head);
System.out.println("合并两个链表:");
Node addListById = addListById(linkedList.getHead(), linkedList1.getHead());
showList(addListById);
// System.out.println("删除节点前----------------------");
//
// System.out.println("逆序打印链表---------------------- ");
// linkedList.rePrintList(linkedList.head);
//
// System.out.println("反转链表--------------------------");
// Node node = linkedList.reLinkedList(linkedList.head);
// showList(node);
//
// System.out.println("删除节点后----------------------");
// linkedList.deleteNodeById(6);
// linkedList.showList();
// System.out.println("修改节点后-----------------------");
// Node node=new Node(1,"123");
// linkedList.updateNode(node);
// linkedList.showList();
// linkedList.getNodeById(1);
// int count = linkedList.getCount();
// System.out.println(count);
// System.out.println(linkedList.findLastIndexNode(-1));
}
/**
* 显示链表
* @param head 链表头节点
*/
public static void showList(Node head){
if (head.next==null){
System.out.println("链表为空,无法遍历");
}else {
Node temp=head.next;
while (temp!=null){
System.out.println("Node{id="+temp.id+",name="+temp.name+"}");
temp=temp.next;
}
}
}
public static Node addListById(Node head1,Node head2){
if (head1.next==null||head2.next==null){
return null;
}else if (head1.next!=null&&head2.next==null){
return head1;
}else if (head2.next!=null&&head1.next==null){
return head2;
}else{
Node newNode=new Node(0,"");
Node cur=newNode;
Node temp1=head1.next;
Node temp2=head2.next;
while (temp1!=null&&temp2!=null){
if (temp1.id<= temp2.id){
cur.next=temp1;
temp1=temp1.next;
cur=cur.next;
}else {
cur.next=temp2;
temp2=temp2.next;
cur=cur.next;
}
}
if (temp1!=null){
cur.next=temp1;
temp1=temp1.next;
cur=cur.next;
}
if (temp2!=null){
cur.next=temp2;
temp2=temp2.next;
cur=cur.next;
}
return newNode.next;
}
}
}
class SingleLinkedList{
//先初始化一个头节点,头节点不要动,不要存放具体数值
Node head =new Node(0,"");
public Node getHead() {
return head;
}
/**
* 把元素添加到链表的最后
* @param node
*/
public void addNode(Node node){
Node temp=head;
while (true){
if (temp.next==null){
temp.next=node;
break;
}
temp=temp.next;
}
}
/**
* 按照节点id顺序添加节点
* 思路:
* 按顺序添加节点,有三种情况
* 1、链表为空,直接添加
* 2、节点重复,无法添加
* 3、找到合适添加节点的位置,添加节点
* 先设置两个辅助节点,一个是指向头节点的first,一个是指向头节点的下一个节点的second
* 利用这个两个辅助节点遍历链表,当second.id>node.id时,就是应该插入的位置
* 这时候:first.next=node,node.next=second
*/
public void addNodeById(Node node){
Node first=head;
Node second=head.next;
//利用i来标记情况:i=1,表示节点重复,i=2,表示找到添加节点的位置
int i=0;
if (second==null){
//说明链表为空,直接在添加
first.next=node;
}else {
//说明链表不为空
while (second!=null){
if (second.id==node.id){
i=1;
break;
}
if (second.id> node.id){
i=2;
break;
}
first=first.next;
second=second.next;
}
if (i==1){
//说明id重复
System.out.println("要添加的节点id已经存在,无法重复添加!");
}else if (i==2){
//找到合适的位置
first.next=node;
node.next=second;
}else {
//说明遍历完链表了,但是还没有找到合适的位置,直接在末尾添加
first.next=node;
}
}
}
/**
* 修改节点,修改节点的时候,id不能变,否则就是添加节点了
* 分为三种情况:
* 1、链表空,无法修改
* 2、找不到id号,无法修改
* 3、找到id号,成功修改
* @param node
*/
public void updateNode(Node node){
Node temp=head.next;
//用来标识是否找到需要修改的节点,false代表没有找到,true代表找到了,默认为false
boolean flag=false;
if (temp==null){
//说明链表为空,无法修改
System.out.println("链表为空,无法修改");
}else {
//说明链表不为空,需要遍历链表
while (temp!=null){
if (temp.id==node.id){
flag=true;
break;
}
temp=temp.next;
}
//遍历结束后判断是否找到需要修改的节点
if (flag){
temp.name=node.name;
}else {
//说明没有找到
System.out.println("没有找到需要修改的节点!");
}
}
}
/**
* 根据id号查询节点信息
* 分为三种情况:
* 1、链表为空,无法获取
* 2、没有这个id号,无法获取
* 3、找到这个id号,返回节点
*/
public void getNodeById(int id){
Node temp=head.next;
//false表示没有找到这个id,true代表已找到
boolean flag=false;
if (temp==null){
System.out.println("链表为空,无法获取");
}else {
while (temp!=null){
if (temp.id==id){
flag=true;
break;
}
temp=temp.next;
}
if (flag){
//说明找到了
System.out.println("查找的节点为:node{id="+temp.id+",name="+temp.name+"}");
}else {
//说明没有找到
System.out.println("链表中没有需要查询的数据!");
}
}
}
/**
* 根据节点id删除节点,删除节点时需要找到待删除节点的前一个位置,所有是temp.next!=null
* 分为三种情况:
* 1、链表为空,无法删除
* 2、找打不到需要删除的id,无法删除
* 3、找打需要删除的id,删除节点
*/
public void deleteNodeById(int id){
Node temp= head;
boolean flag=false;
if (temp.next==null){
System.out.println("链表为空,无法删除节点!");
}else {
//链表不为空,可以删除节点
while (temp.next!=null){
if (temp.next.id==id){
//说明找到了
flag=true;
break;
}
temp=temp.next;
}
if (flag){
temp.next=temp.next.next;
System.out.println("删除成功!");
}else {
System.out.println("没有找到需要删除的节点,无法删除");
}
}
}
/**
* 显示列表
* @param head 列表的头节点
*/
public void showList(Node head){
Node temp=head.next;
if (temp==null){
System.out.println("链表为空,无法遍历!");
}
while (true){
if (temp==null){
break;
}
System.out.println("Node{id="+temp.id+",name="+temp.name+"}");
temp=temp.next;
}
}
/**
* 返回链表的有效个数,不统计头节点,因为头节点没有数据
* @return
*/
public int getCount(){
Node temp=head.next;
int ans=0;
while (temp!=null){
ans++;
temp=temp.next;
}
return ans;
}
/**
* 查找单链表中的倒数第k个节点
* @param k
* @return
*/
public Node findLastIndexNode(int k){
int count=0;
Node temp=head.next;
while (temp!=null){
count++;
temp=temp.next;
}
Node cur=head;
//查找倒数第k个节点,就是正数第count-k+1个
//如果头节点是有数据的,那么就是count-k次循环
//对k做一个校验,k不能大于count,也不能小于1
if (k>count||k<1){
//k是不能大于count的
return null;
}else {
for (int i = 0; i < count-k+1; i++) {
cur=cur.next;
}
return cur;
}
}
/**
* 反转链表
* 思路:先创建一个反转链表的头节点 Node re,然后在利用两个辅助节点遍历链表 Node cur = head.next ,Node next=null
* 先将cur的下一个节点保存:next=cur.next,方便遍历
* 然后再将re.next付给cur.next,在将re.next连向cur
* 这里需要看成指向,而不是赋值
* (先把我的给你,在把你的给我)
* @param head
* @return
*/
public Node reLinkedList(Node head){
if (head.next==null||head.next.next==null){
return head;
}
Node cur=head.next;
Node next=null;
Node re=new Node(0,"");
while (cur!=null){
next=cur.next;
cur.next=re.next;
re.next=cur;
cur=next;
}
head.next=re.next;
return head;
}
/**
* 从尾到头打印链表
* 1、先将链表反转,在打印,这样做的问题是会将链表的结构破坏
* 2、先遍历链表,将链表放入一个栈,然后在弹出栈
*/
public void rePrintList(Node head){
if (head.next==null){
//链表为空
System.out.println("链表为空,无法逆序打印!");
}else {
//链表不为空
Stack<Node> stack=new Stack<Node>();
Node temp=head.next;
//遍历链表
while (temp!=null){
//将链表入栈
stack.add(temp);
temp=temp.next;
}
//出栈
while (stack.size()>0){
System.out.println(stack.pop());
}
}
}
}
class Node{
int id;
String name;
Node next;
public Node() {
}
public Node(int id, String name) {
this.id = id;
this.name = name;
}
public Node(Node next) {
this.next = next;
}
@Override
public String toString() {
return "Node{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
单向链表增删改查
最新推荐文章于 2023-11-13 18:47:45 发布