1、稀疏数组
稀疏数组:当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。 稀疏数组的处理方法是: 1) 记录数组一共有几行几列,有多少个不同的值 2)把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
package shulie;
/*
稀疏数组:当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方法是:
1) 记录数组一共有几行几列,有多少个不同的值
2)把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
*/
//距离一个数组,然后只有某些位置上的数不是零,其余的全部为0
public class SaprseAyyar {
public static void main(String[] args) {
int arr_begin[][]=new int[10][10];
arr_begin[3][5]=5;
arr_begin[4][9]=1;
arr_begin[7][3]=4;
System.out.println("未压缩前");
for(int arr[]:arr_begin){
for(int x : arr){
System.out.print(x+" ");
}
System.out.println();
}
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 5 0 0 0 0
// 0 0 0 0 0 0 0 0 0 1
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 4 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0
/*
类似这样的一个数组,大多数的数据对于我们来说是没有用的,没有必要全部存储,我们只要存储必要的信息就可以了。此时就会用到稀疏数组
1、遍历该数组,找出该数组有多少个不为零的数,将不为零的数的总数记为sum
2、构造一个二维数组 int sparseAarray[sum+1][3]
3、该二维数组记录的是被压缩数组的信息
sparseArray[0][0]:记录的是被压缩数组的行数
sparseArray[0][1]:记录的是被压缩数组的列数
sparseArray[0][2]:记录的是被压缩数组的不为零的数的个数(个人觉得这个似乎没有必要)
sparseArray[1][0]:记录的是被压缩数组的第一个不为零的数的行坐标
sparseArray[1][1]:记录的是被压缩数组的第一个不为零的数的列坐标
sparseArray[1][2]:记录的是被压缩数组的的第一个不为零的数的值
.......后面的仿照sparseArray[1]
*/
int sum=0;
for(int arr[]:arr_begin){
for(int x : arr){
if(x!=0)
sum++;
}
}
System.out.println("sum="+sum);
int sparseArray[][]=new int[sum+1][3];
sparseArray[0][0]=arr_begin.length;
sparseArray[0][1]=arr_begin[0].length;
sparseArray[0][2]=sum;
int j=1;
for (int i = 0; i < arr_begin.length; i++) {
for(int k=0;k<arr_begin[0].length;k++){
if(arr_begin[i][k]!=0){
sparseArray[j][0]=i;
sparseArray[j][1]=k;
sparseArray[j][2]=arr_begin[i][k];
j++;
}
}
}
System.out.println("压缩后");
for(int arr[] : sparseArray){
for(int x : arr){
System.out.print(x+" ");
}
System.out.println();
}
int arr[][]=new int[sparseArray[0][0]][sparseArray[0][1]];
for(int i=1;i<=sparseArray[0][2];i++){
arr[sparseArray[i][0]][sparseArray[i][1]]=sparseArray[i][2];
}
System.out.println("复原");
for(int arr1[] : arr){
for(int x : arr1){
System.out.print(x+" ");
}
System.out.println();
}
}
}
2、队列
数组模拟队列 ➢队列本身是有序列表,若使用数组的结构来存储队列的数据 maxSize是该队列的最大容量。 ➢因为队列的输出、输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变, 该程序旨在使用数组来模拟队列,模拟队列有同一个特点就是,当rear<front且front-rear=1时判定队列处于满状态,无法添加数据,也就是他俩之间有一个活动的空位。
package shulie;
import java.util.Scanner;
/*数组模拟队列
➢队列本身是有序列表,若使用数组的结构来存储队列的数据
maxSize是该队列的最大容量。
➢因为队列的输出、输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,
而rear则是随着数据输入而改变,
*/
//该程序旨在使用数组来模拟队列,模拟队列有同一个特点就是,当rear<front且front-rear=1时判定队列处于满状态,无法添加数据,也就是
//他俩之间有一个活动的空位。
public class ArrayToQueue {
int arr[];//对象中的数组
//front指向的是数组的第一位
int front;
//rear指向的是队列中的最后一个元素的后一个位置
int rear;
int maxsize;
public ArrayToQueue(int maxsize){
arr=new int[maxsize];
front=0;
rear=0;
this.maxsize=maxsize;
}
//判断队列是否填满
public boolean isFull(){
//
return (rear+1+maxsize)%maxsize==front;
}
//判断队列是否为空
public boolean isEmpty(){
//因为rear指向的是最后一个元素的后一位元素,所以当rear==front时,队列为空
return rear==front;
}
//添加元素
public void addQueue(int num){
if(!isFull()){
//添加元素,并移动rear的位置,因为是一个可复用的队列,因此,rear可能会经过maxsize-1之后,从零开始变大
arr[rear]=num;
rear=(rear+1)%maxsize;
}else{
System.out.println("队列已满,无法实现添加操作");
}
}
//使队列中的第一个元素出队列
public void getFirst(){
if(!isEmpty()){
System.out.println("第一个元素是"+arr[front]);
//front也会经过maxsize-1之后,从零开始变大
front=(front+1)%maxsize;
System.out.println(front);
}else{
System.out.println("队列为空,无法进行该操作");
}
}
//查看队列
public void showQueue(){
if(!isEmpty()){
/* if(rear>front){
for (int i=front;i<rear;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
}else{
for(int i=front;i<maxsize;i++){
System.out.println(arr[i]+" ");
}
for(int i=0;i<rear;i++){
System.out.println(arr[i]+" ");
}
}*/
int i=front;
while(i<front+size()){
//淦 看来好久没动脑子了
/* if(i>=maxsize){
System.out.println(arr[i%maxsize]);
}else{
System.out.println(arr[i]);
}*/
System.out.println("arr["+i%maxsize+"]="+arr[i%maxsize]);
i++;
}
}else{
System.out.println("队列为空,无法进行该操作");
}
}
public void getFront(){
System.out.println("Front="+front);
}
public void getRear(){
System.out.println("Rear="+rear);
}
public int size(){
return (rear+maxsize-front)%maxsize;
}
public static void main(String[] args) {
ArrayToQueue queue=new ArrayToQueue(5);
boolean state=true;
Scanner scan=new Scanner(System.in);
while(state){
System.out.println("a) :向队列中添加数据");
System.out.println("g) :查看队列中的第一个数据,并使其出队列");
System.out.println("s) :查看队列所有的数据");
System.out.println("e) :退出程序");
System.out.println("c) :查看队列的数据个数");
System.out.println("f) :查看front");
System.out.println("r) :查看rear");
System.out.print("请输入您的选择: ");
char ch=scan.next().toCharArray()[0];
System.out.println(ch);
switch (ch){
case 'a':
System.out.print("请输入您想要添加的数据:");
int addBase= scan.nextInt();
queue.addQueue(addBase);
break;
case 'c':
System.out.println("已添加的数据个数为"+queue.size());
break;
case 'g':
queue.getFirst();
break;
case 's':
queue.showQueue();
break;
case 'r':
queue.getRear();
break;
case 'f':
queue.getFront();
break;
case 'e':
state=false;
break;
}
}
System.out.println("程序已退出");
}
}
3、 链表
1、单向链表
package shulie;
import java.util.Objects;
import java.util.Stack;
//该程序模拟单向链表,但是链表中的数据顺序时就是我们添加数据的顺序,我们需要非添加顺序顺序的链表,也就需要我们做一些改动,在添加类的属性之中添加一个
//position属性,以便确定添加的数据在链表中的位置
public class LinkListDemo {
public static void main(String[] args) {
Person p1=new Person("懒羊羊",4,5);
Person p2=new Person("喜羊羊",4,4);
Person p3=new Person("沸羊羊",4,1);
Person p4=new Person("暖羊羊",4,6);
Person p5=new Person("美羊羊",4,3);
Person p6=null;
LinkList list=new LinkList();
list.addDataBase(p1);
list.addDataBase(p2);
list.addDataBase(p3);
list.addDataBase(p4);
list.addDataBase(p5);
list.addDataBase(p6);
list.showDataBase();
list.deleteDateBase(p3);
list.showDataBase();
System.out.println("修改后");
list.changeDataBase(new Person("慢羊羊",6,8));
list.showDataBase();
System.out.println(list.size());
for (int i = 1; i < 5; i++) {
System.out.print("获取倒数第"+i+"个节点:");
System.out.println(list.getReciprocal(i));
}
System.out.println("--------------反转后的原链表---------------");
list.reverse();
list.showDataBase();
System.out.println("--------------反转打印链表---------------");
list.reversePrint();
System.out.println("---------------list1--------------------");
LinkList list1 = new LinkList();
list1.addDataBase(new Person("喜羊羊",4,4));
list1.addDataBase(new Person("暖羊羊",4,6));
list1.addDataBase(new Person("X羊羊",4,7));
list1.showDataBase();
System.out.println("--------------打印原链表---------------");
list.reverse();
list.showDataBase();
System.out.println("--------------插入顺序的输出(检验作用)---------------");
list.combine(list1);
System.out.println("--------------合并链表---------------");
list.showDataBase();
}
}
class Person {//链表中的数据类型
String name;
int age;
//某一个数据指向另外一个数据
Person next;
int position;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", position=" + position +
'}';
}
public Person(String name, int age, int position){
this.name=name;
this.age=age;
this.position=position;
}
public Person(String name, int age){
this.name=name;
this.age=age;
this.position=position;
}
//重写equals方法,该方法没有next参与判断
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
}
class LinkList {
Person Source = new Person("", 0);
//添加数据
public void addDataBase(Person p) {
if(p==null){
System.out.println("将要添加的数据为空,不予添加!");
return ;
}
//在有了Position属性之后。addDataBase需要修改
//链表中的第一个数据不可以替换
Person temp = Source;
//判断该数据的指向是否为空,如果为空,添加数据,如果不为空,移动指针temp
while (true) {
if (temp.next == null) {
temp.next = p;
break;
}
if (temp.next.position >= p.position) {
p.next = temp.next;
temp.next = p;
break;
}
temp = temp.next;
}
System.out.println("添加成功!");
}
//展示链表中的数据
public void showDataBase() {
if (Source.next == null) {
System.out.println("链表为空,无法进行该操作!");
} else {
Person temp = Source.next;
while (true) {
System.out.println(temp);
if (temp.next == null)
break;
temp = temp.next;
}
}
}
//删除链表中的某一个数据
//找到待删除节点的前一个节点
public void deleteDateBase(Person p) {
if(p==null){
System.out.println("传进来的数据值为null,无法进行该操作!");
}
if (Source.next == null) {
System.out.println("链表为空,无法进行改操作!");
return;
} else {
boolean found = false;
Person temp = Source;
while (temp.next != null) {
if (p.equals(temp.next)) {
found = true;
temp.next = temp.next.next;
System.out.println("成功删除数据!");
return;
}
temp = temp.next;
}
if (!found) {
System.out.println("未找到该数据,无法进行该操作");
}
}
}
//根据编号修改数据
public void changeDataBase(Person p) {
if (Source.next == null) {
System.out.println("链表为空,无法进行该操作");
} else {
boolean found = false;
Person temp = Source.next;
while (temp != null) {
if (temp.position == p.position) {
found = true;
temp.name = p.name;
temp.age = p.age;
return;
}
temp = temp.next;
}
if (!found) {
System.out.println("该位置不存在数据,无法进行改操作!");
}
}
}
//获取单链表的存储数据的个数
public int size(){
int capacity=0;
Person temp=Source.next;
while(temp!=null){
capacity++;
temp=temp.next;
}
return capacity;
}
//获取倒数第reciprocalPosition个数据
public Person getReciprocal(int reciprocalPosition){
int sum=size();
if(sum==0){
System.out.println("链表为空,无法进行该操作!");
return null;
}
if(reciprocalPosition>sum||reciprocalPosition<=0){
System.out.println("输入的reciprocalPosition不合法");
return null;
}else{
int position=1;
Person temp=Source.next;
while(temp!=null){
if(position==sum-reciprocalPosition+1)
break;
temp=temp.next;
position++;
}
return temp;
}
}
//反转链表
//思路为创建一个Person类的对象head作为另一个链表的头,然后从Source链表中不断取出Source.next,然后将Source.next添加到head链表的第一位
//直至Source.next=null,此时Source链表中的数据已经全部转移到head链表中去,并且因为我们从Source链表的第一位取的数据,然后放在head的第一位,
//所以原来在Source中的数据在head中的顺序也会变成倒序
//在取出Source.next的过程中,Source链表中的数据在不断地减少。
public void reverse(){
if(Source.next==null){
System.out.println("该链表为空,无法反转!");
throw new RuntimeException();
}
Person head=new Person("",0);
Person temp=Source.next;
while(temp!=null){
Person laterPer=head.next;
Person laterPer1=temp.next;
head.next=temp;
temp.next=laterPer;
temp=laterPer1;
}
Source.next=head.next;
}
public void reversePrint(){
if(Source.next==null){
System.out.println("链表为空,无法进行该操作!");
return;
}
Stack<Person> stack = new Stack<>();
Person temp=Source.next;
while(temp!=null){
stack.add(temp);
temp=temp.next;
}
//Object pop():移除并返回堆栈的顶部元素
while(stack.size()>0){
System.out.println(stack.pop());
}
}
//合并两个有序的单链表,合并之后的链表依然有序
public void combine(LinkList list1){
if(list1.Source.next==null){
System.out.println("插入的链表为空,插入无效!");
return;
}
// //方法一:
// Person temp=list1.Source.next;
// Person next;
// while(temp!=null){
// next=temp.next;
// Person temp1=Source;
// while(true){
// if(temp1.next==null||temp1.next.position>=temp.position){
// break;
// }
// temp1=temp1.next;
// }
// temp.next=temp1.next;
// temp1.next=temp;
// temp=next;
// }
/* //方法二:
// 我就喜欢这样,上面的花里胡哨,虽然也是我的写的,淦
Person temp=list1.Source.next;
while(temp!=null){
this.addDataBase(new Person(temp.name, temp.age,temp.position));
temp=temp.next;
}*/
//方法三:
Person temp1=list1.Source.next;
Person temp2=Source.next;
LinkList linkList = new LinkList();
Person temp=linkList.Source;
while(true){
if(temp1==null&&temp2==null){
break;
}else if(temp2==null){
temp.next=temp1;
temp1=temp1.next;
temp=temp.next;
temp.next=null;
System.out.println("插入"+temp);
}else if(temp1==null){
temp.next=temp2;
temp2=temp2.next;
temp=temp.next;
temp.next=null;
System.out.println("插入"+temp);
}else if(temp2.position>=temp1.position){
temp.next=temp1;
temp1=temp1.next;
temp=temp.next;
temp.next=null;
System.out.println("插入"+temp);
}else if(temp2.position<temp1.position){
temp.next=temp2;
temp2=temp2.next;
temp=temp.next;
temp.next=null;
System.out.println("插入"+temp);
}
}
this.Source.next= linkList.Source.next;
}
}
2、双向链表
package shulie;
import java.util.Objects;
//本程序实现双向链表
public class DoubleLinkedLIstDemo {
public static void main(String[] args) {
DoubleLinkedList list = new DoubleLinkedList();
for (int i = 0; i < 5; i++) {
list.add( new DataClass(""+i,i,i));
}
System.out.println("---------原始数据-------------------");
list.showDataBase();
System.out.println("---------添加数据-------------");
list.add(new DataClass("8",8,8));
list.add(new DataClass("6",6,6));
list.showDataBase();
}
}
class DataClass {
String name;
int age;
int position;
DataClass pre;
DataClass next;
@Override
public String toString() {
return "DataClass{" +
"name='" + name + '\'' +
", age=" + age +
", position=" + position +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DataClass dataClass = (DataClass) o;
return age == dataClass.age && position == dataClass.position && Objects.equals(name, dataClass.name);
}
public DataClass(String name, int age, int position) {
this.name = name;
this.age = age;
this.position = position;
}
}
class DoubleLinkedList{
DataClass Head=new DataClass("",0,0);
//添加方法:该方法只添加单个的数据而不是因为添加了一个数据而添加一串数据
public void add(DataClass data){
if(data==null){
System.out.println("将要添加的数据为空,添加无效");
return;
}
//
data.next=null;
DataClass temp=Head;
while(temp.next!=null){
if(data.position<=temp.next.position)
break;
temp=temp.next;
}
if(temp.next==null){
temp.next=data;
data.pre=temp;
}else{
temp.next.pre=data;
data.pre=temp;
data.next=temp.next;
temp.next=data;
}
}
public void showDataBase(){
if(Head.next==null){
System.out.println("链表为空,无法进行该操作!");
return ;
}
DataClass temp=Head.next;
while(temp!=null){
System.out.println(temp);
temp=temp.next;
}
}
}
4、单向环
package shulie;
/*
Josephu问题为:设编号为1, 2, ..n的n个人围坐一圈,约定编号为k (1<=k<=n)的人从1开始报数,数到m的那个人出列,它
的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
n=5,即有5个人
k=1,从第一个人开始报数
m=2,数2下
*/
import java.io.BufferedInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class CircleLinkedListDemo {
public static void main(String[] args) throws IOException {
//感觉我似乎有病。。。。
// byte[] b=new byte[10];
// System.out.print("请输入n:");
// int len=System.in.read(b);
for (int i = 0; i < len-1; i++) {
System.out.println(b[i]);
}
System.out.println(len-1);
System.out.println(new String(b,0,len-1));
// int n=Integer.parseInt(new String(b,0,len-1));
// System.out.println("n="+n);
Scanner scan=new Scanner(System.in);
// int n=scan.nextInt();
int m=5;
int n=7;
CircleLinkedList list = new CircleLinkedList();
for (int i = 1; i < 6; i++) {
list.add(new GameClass(i));
}
list.showDataBase();
// for (int i = 1; i < 7; i++) {
//
// list.delete(i);
// list.showDataBase();
// }
System.out.println("--------游戏开始!----------");
list.game(3,2);
}
}
//草 尾部指向Head,我承认我是笨比,在尾部指向上老是改变。
class GameClass{
int position;
GameClass next;
public GameClass(int position){
this.position=position;
next=null;
}
@Override
public String toString() {
return "GameClass{" +
"position=" + position +
'}';
}
}
class CircleLinkedList{
//单向环
GameClass Head=new GameClass(0);
public void add(GameClass game){
if(game==null){
System.out.println("添加的数据为空,无法添加该数据!");
return ;
}
game.next=null;
// 没有顺序的加入
GameClass temp=Head.next;
if(temp!=null){
System.out.println(1);
while(temp.next!=Head){
temp=temp.next;
}
temp.next=game;
game.next=Head;
}else{
System.out.println(2);
Head.next=game;
game.next=Head;
}
System.out.println("添加成功!");
}
public void delete(int position){
if(position==0){
System.out.println("The value of position is invalid!");
return ;
}
if(Head.next==null){
System.out.println("Your CircleLinkedList is empty! So this is no database! ");
return;
}
GameClass temp=Head;
while(true){
if(position==temp.next.position)
break;
if(temp.next==Head){
System.out.println("该数据不存在,无法删除!");
return;
}
temp=temp.next;
}
temp.next=temp.next.next;
System.out.println("删除成功!");
}
public void showDataBase(){
if(Head.next==null){
System.out.println("Your CircleLinkedList is empty! So this is no database!");
return;
}
GameClass temp=Head.next;
while(temp!=Head){
System.out.println(temp);
temp=temp.next;
if(temp==Head.next){
break;
}
}
}
public void game(int position1,int num){
if(Head.next==null){
System.out.println("环形列表中没有数据,无法开始游戏!");
}
GameClass temp=Head.next;
int i=1;
while(i<position1){
temp=temp.next;
if(temp!=Head){
i++;
}
}
System.out.println("i="+i);
i=1;
System.out.println(temp);
while(true){
if(temp.next.next==temp){
System.out.println(temp+"出列");
delete(temp.position);
System.out.println("游戏结束");
return;
}
if(i%num==0){
System.out.println("i="+i+",num="+num);
System.out.println(temp+"删除");
GameClass temp1=temp;
this.delete(temp.position);
System.out.println("---------剩余数据----------------");
this.showDataBase();
}
while(temp.next==Head){
temp=temp.next;
}
temp=temp.next;
i++;
}
}
}