Data structure and algorithm_linked list_singly linked list

1. What is a linked list?
Answer: A linked list is a very commonly used data structure. It is an ordered linear structure in logic structure , and the chain storage is used for storage, which means that the two data in the actual memory are not necessarily continuous . The node is the basic storage unit of the linked list, and each node is divided into a data domain and a next domain.
It can be seen from here
Looking closely at this picture, the linked list is divided into two types: head node and headless node. This picture has a head node. You can find that the two adjacent nodes a1 and a2 are not adjacent. The nodes are connected by storing the address of the next node through the next pointer field.

2. What are the advantages of linked lists?
Insert picture description here
Answer: The linked list is logically continuous, which is convenient for people to use to realize specific functions. The storage can be discontinuous, making better use of trivial memory cells. Secondly, it can dynamically add nodes without having to determine the size of the array like an array, causing a waste of space. Therefore, it can save memory space and improve storage utilization.

3. The specific implementation of the
singly linked list The implementation here is to use the singly linked list to store the numbers, names, and nicknames of the Heroes of the Water Margin.

package com.xiaofan.LinkedList;

public class SingleLinkedListDomo {

	public static void main(String[] args) {
		//test
		//创建节点
		HeroNode hero1=new HeroNode(1,"宋江","及时雨");
		HeroNode hero2=new HeroNode(2,"卢俊义","玉麒麟");
		HeroNode hero3=new HeroNode(3,"吴用","智多星");
		HeroNode hero4=new HeroNode(4,"林冲","豹子头");
		
		//创建链表
		SingleLinkedList list = new SingleLinkedList();
		//add
//		list.add(hero1);
//		list.add(hero4);
//		list.add(hero2);
//		list.add(hero3);
		
		//addbyOrder
		list.addbyOrder(hero1);
		list.addbyOrder(hero4);
		list.addbyOrder(hero2);
		list.addbyOrder(hero3);
		
		//测试反转
		list.show();
		list.reverseList(list.getHead());
		list.show();
		
/*		
		//修改函数测试
//		list.show();
//		
//		HeroNode newHeroNode = new HeroNode(2,"小卢","火麒麟");
//		
//		list.updata(newHeroNode);
		
		//测试一个节点
		list.delete(1);
		list.delete(2);
		list.delete(2);
		list.delete(5);
		
		list.show();
*/		
		
	}

}

//定义一个SingleLinkedList,来管理我们的链表
class SingleLinkedList{
	//先初始化一个头结点
	private HeroNode head = new HeroNode(0,"","");
	
	//添加节点到单链表中
	//不考虑顺序插入时
	//1、找到最后的一个节点
	//2、将最后的节点的next指向当前节点
	public void add(HeroNode heroNode) {
		//因为head不能动,创建一个辅助节点temp
		HeroNode temp = head;
		//遍历链表,找到最后
		while(true) {
			//temp.next==null,则找到最后
			if(temp.next==null) {
				break;
			}
			temp = temp.next;
		}
		//退出循环时,temp就指向了链表的最后
		//将这个节点的next指向当前的节点
		temp.next = heroNode;
	}
	
	//按顺序添加
	public void addbyOrder(HeroNode heroNode) {
		//因为只有向后的指针,所以找添加位置的前一个节点,才能插入
		HeroNode temp = head;
		boolean flag = false;
		while(true) {
			if(temp.next==null) {//说明已经到最后了,必须跳出循环
				break;
			}
			if(temp.next.no > heroNode.no) {//位置找到了,即找到第一个大于插入节点编号的节点
				break;
			}else if(temp.next.no == heroNode.no) {//说明编号已经存在
				flag=true;
				break;
			}
			temp=temp.next;
		}
		//判断flag的值
		if(flag) {//说明重复插入
			System.out.printf("重复插入%d节点",heroNode.no);
		}
		else {
			//可以插入
			heroNode.next=temp.next;
			temp.next=heroNode;
		}
	}
	
	//修改节点的信息,编号不能改
	//根据编号进行修改
	public void updata(HeroNode newheroNode) {
		//判断链表是否为空
		if(head.next == null) {
			System.out.println("链表为空");
			return;
		}
		//找到需要修改的节点,根据no编号
		//定义一个辅助变量
		HeroNode temp = head.next;
		boolean flag = false;//表示是否找到该节点
		while(true) {
			if(temp == null) {//到链表的最后
				break;
			}
			if(temp.no == newheroNode.no) {//找到了
				flag = true;
				break;
			}
			temp=temp.next;
		}
		//根据flag 判断是否找到需要修改的节点
		if(flag) {
			temp.name=newheroNode.name;
			temp.nikeName=newheroNode.nikeName;
		}
		else {
			System.out.printf("没有找到编号为%d的节点\n",newheroNode.no);
		}
	}
	
	//删除节点
	//1.head 不能动,因此我们需要一个temp辅助节点找到待删除节点的前一个节点
	//2.说明我们在此时,要temp.next.no和需要删除的节点的no比较
	
	public void delete(int no) {
		
		//找到需要删除的节点,根据no编号
		//定义一个辅助变量
		HeroNode temp = head;
		boolean flag = false;//表示是否找到该节点
		while(true) {
			if(temp.next == null) {//到链表的最后
				break;
			}
			if(temp.next.no == no) {//找到了要删除的节点的前一个节点
				flag = true;
				break;
			}
			temp=temp.next;//后移遍历
		}
		//根据flag 判断是否找到需要删除的节点
		if(flag) {
			temp.next = temp.next.next;
		}
		else {
			System.out.printf("没有找到要删除的编号为%d的节点\n",no);
		}
		
	}
	
	//显示链表
	public void show() {
		//判断链表是否为空
		if(head.next==null) {
			System.out.println("链表为空");
			return;
		}
		//使用temp遍历链表
		HeroNode temp = head.next;
		while(true) {
			//判断是否到最后
			if(temp==null) {
				break;
			}
			//输出节点信息
			System.out.println(temp);
			temp=temp.next;
		}
	}
	
	//将单链表反转
	public static void  reverseList(HeroNode head) {
		//如果链表只有一个节点或者为空,则无需反转
		if(head.next==null || head.next.next==null) {
			return;
		}
		//定义一个辅助的节点,用来遍历节点
		HeroNode cur = head.next;
		HeroNode next = null;//指向当前节点【cur】的下一个节点
		HeroNode reverseHead = new HeroNode(0,"","");
		//遍历原来的链表
		//每遍历一个节点,就将其取出,并放在reverseHead的前端
		while(cur!=null) {
			next = cur.next;//先暂时保存当前节点的下一个节点
			cur.next = reverseHead.next;//将cur的下一个节点指向新的链表的前端
			reverseHead.next=cur;//反转头结点的连接上反转链表
			cur = next;//让cur后移
		}
		//将head.next指向reverseHead.next,将链表反转
		head.next=reverseHead.next;
	}
	
	public HeroNode getHead() {
		return this.head;
	}
}



//定义一个HeroNode,每个HeroNode就是一个结点
class HeroNode{
	public int no;
	public String name;
	public String nikeName;
	public HeroNode next;
	
	//构造器
	public HeroNode(int no,String name,String nikeName) {
		this.no=no;
		this.name=name;
		this.nikeName=nikeName;
	}
	//为了便于显示,重写toString

	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + ", nikeName=" + nikeName +']';
	}
	

Published 27 original articles · praised 2 · visits 680

Guess you like

Origin blog.csdn.net/qq_44273739/article/details/104855665