数组和链表与Josephus问题(Java)

#序言
##这算是我在CSDN里的第一篇文章,希冀着以此来纪念我的学习生涯并加深学习相关的专业知识。给自己加油打气,希望能坚持下去!
好了,那正式开始!

#数组和链表
##数组
它的最大特征就是用一组连续的内存空间来存储一组具有相同类型的数据,正因如此,它才有“随机访问”的特性,但这也让删除、插入操作变得非常低效(平均时间复杂度为O(n)).

##链表
它通过“指针”将一组零散的内存块串联起来使用,不需要一块连续的内存空间。接下来讲一下几种基本的链表类型。

###单链表
链表通过指针将零散内存块串联,而内存块亦称为链表的“结点”。结点需要存储数据和下一个结点的地址。
在这里插入图片描述由图可知,链表通过头结点和借助后继指针进行遍历,时间复杂度为O(n);而插入和删除的时间复杂度为O(1),因为链表并不需要保持内存的连续性。

###双向链表
此链表有两个指针:前驱指针pred和后继指针next;所以双向链表要比单链表占用更多的内存空间,但插入、删除操作更为高效。
在这里插入图片描述
###循环链表
循环链表是一种特殊的单链表,和单链表唯一的差别就在于尾结点。单链表的尾结点指向空地址,而循环链表的尾指针指向链表的头结点。

#练习(Josephus问题)
##问题描述
古代某法官要判决number个犯人的死刑,他有一条荒唐的法律,将犯人站成一个圆圈,从第start个人开始数起,每数到第distance个犯人,就拉出来处决,然后从下一个开始数distance个,数到的人再处决,······直到剩下最后一个犯人予以赦免。

##算法

//顺序表求Josephus
public	Josephus(int number,int start,int distance){
		System.out.println("Josephus("+number+","+start+","+distance+")");
		SeqList<String>list=new SeqList<String>(number);     //创建顺序表实例,构造方法参数指定顺序表容量,省略时取默认值
		for(int i=0;i<number;i++)
			list.insert((char)('A'+i)+"");                                          //顺序表尾插入,O(1)
			System.out.println(list.toString());                              //输出顺序表描述字符串,O(n)
	                                                                                           
			int i=start;         
			while(list.size()>1){                                                     //多于一个元素时循环,计数起始位置
				i=(i+distance-1)%list.size();                                    //遍历顺序表
				System.out.println("删除"+list.remove(i).toString()+", ");     //删除i位置对象,O(n)
				System.out.println(list.toString());                       
			}
		System.out.println("被赦免者是"+list.get(0).toString());          //get(0)获得元素,O(1)
	}
//单链表求Josephus
	public void Josephus(int number,int start,int distance){
		if(number<1&&start<0&&distance<1)
			System.out.println("输入数据错误!");
		System.out.println("Josephus环长度为 "+number+",初始位置为"+start+",计数长度为"+distance);
		SinglyList<Integer>list=new SinglyList<Integer>();     //创建单链表实例
		Node<Integer>p=list.head;                                          //p指向头结点
		for(int i=number;i>0;i--)
			list.insert(0,(Integer)i);                                                 //头插入	
		System.out.println(list);
		for(int j=0;p!=null&&j<start-1;j++) 
			p=p.next;                                                                      //p指向起始位置的前一个结点
		while(number>1){
			for(int k=0;k<distance;k++){                                         //在计数长度内遍历
				p=p.next;
				if(p==null) p=list.head.next;                                     //若指向链表尾则循环到头结点
		    }
			if(p.next==null)p=list.head;                                          //若指向链表尾则循环到头结点
			System.out.print("处刑"+p.next.data+"号犯人");
			p.next=p.next.next;
			number--;
			System.out.print("\n");
		}
		System.out.print("被赦免者是"+list.get(0)+"号犯人");          //get(0)获得元素,O(1)
	}

#结尾
本文章就此结束了,希望大家能给予意见,相互进步。谢谢啦!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qfbt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值