数据结构中基本链表结构特点:
(1)链表是以节点的方式来存储,属于链式存储;
(2)每个节点包含data域,next域:指向下一节点;
(3)链表的各个节点不一定是连续存储;
(4)头节点不存储数据,只用于指向下一个节点。
下面的程序是单向链表的基本操作,增删改查,反转,逆序打印。
package yu.practice03.Linkedlist;
import org.w3c.dom.ls.LSOutput;
import java.util.Stack;
public class singlelistDemo {
public static void main(String[] args) {
PersonNode person01 = new PersonNode(1,"张三","三三");
PersonNode person02 = new PersonNode(2,"李四","四四");
PersonNode person03 = new PersonNode(3,"王五","五五");
PersonNode person04 = new PersonNode(4,"陈六","六六");
LinkedList linkedlist = new LinkedList();
linkedlist.add(person01);
linkedlist.add(person02);
linkedlist.add(person03);
linkedlist.add(person04);
System.out.println("将新节点插入到链表末尾的方法:");
linkedlist.show();
System.out.println("linkedlist链表的有效长度:" + LinkedList.getLength(linkedlist.getHead()));
System.out.println("=======================================================");
System.out.println("将新节点按照num的大小有序插入的方法:");
LinkedList list = new LinkedList();
list.addByOrder(person04);
list.addByOrder(person02);
list.addByOrder(person03);
list.addByOrder(person01);
list.show();
System.out.println("linkedlist链表的有效长度:" + LinkedList.getLength(linkedlist.getHead()));
System.out.println("=======================================================");
System.out.println("删除一个节点:");
list.delete(3);
list.delete(6);
list.show();
System.out.println("=======================================================");
System.out.println("更新一个节点:");
PersonNode person05 = new PersonNode(2,"李子","小五");
list.update(person05);
list.show();
System.out.println("=======================================================");
System.out.println("list链表的有效长度:" + LinkedList.getLength(list.getHead()));
System.out.println("=======================================================");
LinkedList.getKNode(list.getHead(),2);//对应什么参数传入什么参数进去
LinkedList.getKNode(list.getHead(),4);
System.out.println("=======================================================");
System.out.println("链表反转之后为:" );
LinkedList.reverse(list.getHead());
list.show();
System.out.println("=======================================================");
System.out.println("链表反向打印之后为:" );
list.reversePrint(list.getHead());
}
}
//链表的增删改查
class LinkedList{
//创建一个头节点
private PersonNode head = new PersonNode(0,"","");
public PersonNode getHead(){
return head;
}
//增加一个节点到链表的尾部
//1.找到当前链表的最后一个节点
//2.将节点插入到最后一个节点后
public void add(PersonNode personNode){
PersonNode temp = head;
while(true){
if(temp.next == null){
break;
}
temp = temp .next;
}
temp.next = personNode;//通过参数列表传进来的参数值
}
//第二种方法按照num的顺序来插入节点
public void addByOrder(PersonNode personNode){
PersonNode temp = head;
boolean flag = false;
//遍历找到该节点,找到之后即退出循环做下一步动作;
while(true){
//如果这里直接让temp=head.next,会出现temp.num是空;
if(temp.next == null){
break;
}
if(temp.next.num > personNode.num ){
break;
}
if(temp.next.num == personNode.num){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
System.out.println("要插入的编号为:" + personNode.num + "已经存在,不能插入");
}else{
personNode.next = temp.next;
temp.next = personNode;
}
}
//删除一个节点
public void delete(int num){
PersonNode temp = head;
boolean flag = false;
while(true){
if(temp.next == null){
break;
}
if(temp.next.num == num){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.next = temp.next.next;
}else{
System.out.println("编号为" + num + "的人不存在!");
}
}
//根据编号改变节点的属性
public void update(PersonNode personNode){
PersonNode temp = head;
boolean flag = false;
while(true){
if(temp.next == null){
break;
}
if(temp.next.num == personNode.num){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
//更新的程序忘记
temp.next.name = personNode.name;
temp.next.nickName = personNode.nickName;
}else{
System.out.println("您要更新的成员不存在!");
}
}
//输出链表的有效长度---不包括头长度
public static int getLength(PersonNode head){
PersonNode temp = head.next;
boolean flag = true;
if(head.next == null){
return 0;
}
int i = 0;
while (true){
if(temp == null){
break;
}
i++;
temp = temp.next;
}
return i;
}
//找到倒数第k个节点的信息,在这里传入一个index索引
public static PersonNode getKNode(PersonNode head, int index){
if(head.next == null){
System.out.println("链表为空");
return null;
}
PersonNode temp = head;
int size = getLength(head);
if(index < 0 || index > size){
System.out.println("索引值为" + index + "的值不存在!");
return null;
}
for(int i = 0 ; i < size - index; i++){
temp = temp.next;
}
System.out.println(temp);
return temp;
}
//反转链表
public static void reverse(PersonNode head){
PersonNode cur = head.next;
PersonNode newReverseHead = new PersonNode(0,"","");
PersonNode next = null;
if(head.next == null || head.next.next == null){
return ;
}
while(cur != null){
next = cur.next;
cur.next = newReverseHead.next;
newReverseHead.next = cur;
cur = next;//让cur后移 完成遍历
}
//缺少一步骤,让头指针相连
head.next = newReverseHead.next;
}
//逆向打印链表中的节点
//不可以用反转的方式,因为会破坏单项链表的数据结构
//利用栈先进后出的方式来逆向打印
public static void reversePrint(PersonNode head){
if(head. next == null){
return;
}
//创建一个新的栈
//压栈
Stack<PersonNode> stack = new Stack<PersonNode> ();
PersonNode cur = head.next;
while(cur != null){
stack.push(cur);
cur = cur.next;
}
//遍历栈,将栈中的节点打印出来
while(stack.size()>0){
System.out.println(stack.pop());
}
}
//显示链表
public void show(){
if(head.next == null){
System.out.println("链表为空");
return;//注意这里仍要返回
}
PersonNode temp = head.next;
while(true){
if(temp == null){
break;
}
System.out.println(temp);
temp = temp.next;
}
}
}
//定义链表节点的属性
//person后面什么都没有 修饰符+类名称{}
class PersonNode{
//定义变量时要谨慎使用权限,private仅限于本类中使用
public String name;
public String nickName;
public int num;
public PersonNode next;
//一个标准类通常有:系统默认赠送的一个无参构造,自己定义的有参构造,一个getter,setter
//创建构造器快捷键Alt + insert;
public PersonNode(int num, String name ,String nickName) {
this.num = num;
this.name = name;
this.nickName = nickName;
}
//重写toString 方法,为了清晰显示
@Override
public String toString() {
return"[num = " + num + ", name = " + name + ", age = " + nickName + " ]";
}
}