双向链表的定义:
双向链表的实现
1.代码如下:注意删除时考虑最后一个节点的空指针异常
package List;
public class doublelinkedlistdemo {
public static void main(String[] args) {
//测试
HeroNode2 hero1 = new HeroNode2(1,"宋江","及时雨");
HeroNode2 hero2 = new HeroNode2(2,"卢俊义","玉麒麟");
HeroNode2 hero3 = new HeroNode2(3,"吴用","智多星");
HeroNode2 hero4 = new HeroNode2(4,"林冲","豹子头");
HeroNode2 hero5 = new HeroNode2(5,"史进","九纹龙");
//创建单链表
DoubleLinkedList dt =new DoubleLinkedList();
dt.add(hero1); //添加节点数据
dt.add(hero2);
dt.add(hero3);
dt.add(hero4);
dt.add(hero5);
dt.show(); //显示数据
//修改数据
System.out.println();
HeroNode2 hero6 = new HeroNode2(5,"史进","小花龙");
dt.update(hero6);
dt.show(); //显示数据
//删除数据
System.out.println();
dt.delete(hero5);
dt.show(); //显示数据
}
}
//创建链表属性
class DoubleLinkedList{
//初始化一个头节点
HeroNode2 head = new HeroNode2(0,"","");
//返回头结点
public HeroNode2 getHead() {
return head;
}
//遍历双向链表
public void show() {
if(head.next==null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head.next;
while(true) {
if(temp==null) {break;}
System.out.println(temp);
temp = temp.next;
}
}
//在链表后面进行添加
public void add(HeroNode2 heronode) {
HeroNode2 temp = head;
while(true) {
if(temp.next==null) {
break; //找到最后的位置
}
temp = temp.next;
}//这里执行完就是最好的位置
temp.next = heronode;
heronode.pre = temp;
}
//修改一个节点的内容
public void update(HeroNode2 heronode) {
if(head.next==null) {
System.out.println("无该节点");
return;
}
HeroNode2 temp = head;
boolean flag = false;
while(true) {
if(temp==null) {
break; //已经遍历完
}
if(temp.num==heronode.num) {//编号相同
flag = true;
break; //找到最后的位置
}
temp = temp.next;//继续遍历
}
if(flag) {
temp.name = heronode.name;
temp.pname = heronode.pname;
}else {
System.out.println("无该节点编号匹配");
}
}
//删除一个节点,删除本身即可
public void delete(HeroNode2 heronode ) {
if(head.next==null) {
System.out.println("链表为空");
return;}
HeroNode2 temp = head;
boolean flag =false;
while(true) {
if(temp==null) {break;}
if(temp.num == heronode.num) {
flag = true;
break;
}
temp = temp.next;
}
if(flag) {
temp.pre.next = temp.next;//跳过temp节点,
//若删除的是最后一个节点,考虑空指针异常
if(temp.next!=null) {
temp.next.pre = temp.pre;
}
}else {
System.out.println("无此节点");
}
}
}
//创建节点属性
class HeroNode2 {
public int num; //编号
public String name; //名字
public String pname; //昵称
public HeroNode2 next;//指向下一节点
public HeroNode2 pre; //指向前一个节点
//构造方法
public HeroNode2(int numb,String nameb,String pnameb ) {
this.num = numb;
this.name = nameb;
this.pname= pnameb;
}
//重写toString方法,方便输出信息
@Override
public String toString() {
return "HeroNode2 [num=" + num + ", name=" + name + ", pname=" + pname + "]";
}
}
2.测试结果如下:
2.单向环形链表
最后一位时,还是自己与自己为一个环形链表:
算法模拟过程:
出圈如下:利用两个指针来同时step m-1次(包括本身节点报了m个数),通过这两个指针一前一后进行节点删除
代码如下:
package List;
public class YuesefuPro {
public static void main(String[] args) {
//测试环形链表
CirLinkedList cst = new CirLinkedList();
cst.additems(10); //加入5个成员节点;
cst.showcurnode(); //显示链表节点编号
//测试约瑟夫问题
cst.Getnums(1,2,10);//k,m,number
}
}
//创建环形链表
class CirLinkedList{
//创建第一个节点,且无编号
private Nodeitems first = null; //定义头节点
//添加队员节点,形成环形链表
public void additems(int num) {
if(num<1) { System.out.println("输入错误");
return;
}
Nodeitems temp = null; //作为记录指针,记录当前的添加节点
//使用for循环来创建循环链表
for(int i = 1;i<=num;i++) {
Nodeitems curnode = new Nodeitems(i);//这是要添加的新节点
if(i==1) {
first = curnode; //记录第一个节点
first.setNext(first); //指向自己,构成环形链表
temp = first;
}else {
temp.setNext(curnode); //指向新的下一节点
curnode.setNext(first); //指向首节点
temp = curnode; //记录该节点,好指向下一节点
}
}
}
//约瑟夫问题构建
/**
* @param k 是开始数数的节点
* @param m 数多少次数
* @param num 链表原来的成员个数
*/
public void Getnums(int k,int m,int num) {
//数据的校验
if(first == null || k>num || k<1) {
System.out.println("输入有问题");
return;
}
Nodeitems curbefore = first; //构建第一个报数的前一个指针
//使得前后指针相差一步
while(true) {
if(curbefore.getNext() ==first) {
break;
}
curbefore= curbefore.getNext();
}
//报数初始化,让first移动到第k个,curbefore移动到k-1个
for(int i=0;i<k-1;i++) {
first =first.getNext(); //first为1,需要走k-1步,这里走了k-2步
curbefore = curbefore.getNext(); //比first慢一个指针
}
//开始报m个数,走m-1步,找到要出队的节点
while(true) {
if(curbefore==first) {break;}//只剩下最后一个节点
for(int j=1;j<m;j++) {
first =first.getNext(); //first就是待出队的节点
curbefore = curbefore.getNext(); //比first慢一个指针
}
System.out.println("出圈的节点"+first.getNum());
first = first.getNext();//将待删除节点的下一个赋给前一个节点
curbefore.setNext(first) ; //直接跳过要删除的节点
}
System.out.println("出圈的节点"+first.getNum());
}
//打印链表
public void showcurnode() {
//判断链表为空
if(first == null) {
System.out.println("链表为空");
return;
}
Nodeitems temp = first; //作为记录指针,记录当前的添加节点
while(true) {
System.out.printf("%d \n",temp.getNum());
if(temp.getNext()==first) {
break; //指向第一个节点,遍历完毕
}
temp = temp.getNext(); //向下继续遍历
}
}
}
//创建节点属性
class Nodeitems{
private int num;//编号
private Nodeitems next;//定义指下的指针
public Nodeitems(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Nodeitems getNext() {
return next;
}
public void setNext(Nodeitems next) {
this.next = next;
}
}
测试结果:k=1,m=2,num=5,10