当一个数组中大部分元素为0,或者为同一个值的数组时,可以用稀疏数组来保存该数组
稀疏数组的第一行用来记录该数组共几行几列,并且有多少个不同的值
二维数组转稀疏数组
稀疏数组转二维数组
代码实现
public class SparseArray {
public static void main(String[] args) {
// 创建初始二维数组
int array[][] = new int[11][11];
array[0][1] = 1;
array[1][4] = 2;
array[0][7] = 3;
array[2][5] = 4;
System.out.println("原始二维数组为:");
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.printf("%d\t", array[i][j]);
}
System.out.println();
}
// 获取有效数据的个数
int sum = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] != 0) {
sum++;
}
}
}
// 根据二维数组创建稀疏数组
int sparseArray[][] = new int[sum + 1][3];
// 首元素储存数组的大小和有效数据的个数
sparseArray[0][0] = array.length;
sparseArray[0][1] = array[0].length;
sparseArray[0][2] = sum;
// 遍历原数组并将数据存入稀疏数组
int count = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] != 0) {
count++;
sparseArray[count][0] = i;
sparseArray[count][1] = j;
sparseArray[count][2] = array[i][j];
}
}
}
// 输出稀疏数组信息
System.out.println("稀疏数组:");
for (int i = 0; i < sparseArray.length; i++) {
System.out.printf("%d\t%d\t%d\n", sparseArray[i][0], sparseArray[i][1], sparseArray[i][2]);
}
// 将稀疏数组转换成二维数组
int sparseToArray[][] = new int[sparseArray[0][0]][sparseArray[0][0]];
for (int i = 1; i < sparseArray.length; i++) {
sparseToArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
// 输出转换后数组内容
System.out.println("转换后二维数组为:");
for (int i = 0; i < sparseToArray.length; i++) {
for (int j = 0; j < sparseToArray[i].length; j++) {
System.out.printf("%d\t", sparseToArray[i][j]);
}
System.out.println();
}
}
}
//使用数组模拟队列
public class ArrayQueue{
private int maxSize;
private int front;
private int rear;
private int[] queue;
public ArrayQueue(int queueSize) {
maxSize = queueSize;
front = -1;
rear = -1;
queue = new int[maxSize];
}
//判断队列是否满
public boolean isFull() {
return maxSize==rear+1;
}
//判断队列是否为空
public boolean isEmpty() {
return rear==front;
}
//向队列中添加元素
public void addQueue(int n) {
if (isFull()) {
System.out.println("队列已满");
return;
}
rear++;
queue[rear] = n;
}
//从队列中取出一个元素
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
front++;
return queue[front];
}
//显示队列中的元素
public void showQueue() {
for (int i = 0; i < queue.length; i++) {
System.out.printf("queue[%d]=%d\t",i,queue[i]);
}
}
//显示队列的头信息
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
return queue[front+1];
}
}
以上使用数组模拟队列存在队列不能复用的问题,为解决这个问题引入环形队列
//使用数组模拟环形队列
public class CricleQueue{
private int maxSize;
private int front;
private int rear;
private int[] queue;
public CricleQueue(int queueSize) {
maxSize = queueSize;
front = 0;
rear = 0;
queue = new int[maxSize];
}
//判断队列是否满
public boolean isFull() {
return (rear+1)%maxSize==front;
}
//判断队列是否为空
public boolean isEmpty() {
return rear==front;
}
//向队列中添加元素
public void addQueue(int n) {
if (isFull()) {
System.out.println("队列已满");
return;
}
queue[rear] = n;
rear = (rear+1)%maxSize;
}
//从队列中取出一个元素
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
int n = queue[front];
front = (front+1)%maxSize;
return n;
}
//显示队列中的元素
public void showQueue() {
for (int i = front; i < front + this.size(); i++) {
System.out.printf("queue[%d]=%d\t",i%(maxSize-1),queue[i%maxSize]);
}
}
//显示队列大小
public int size() {
return (rear+maxSize-front)%maxSize;
}
//显示队列的头信息
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
return queue[front];
}
}
public class SingleLinkedList {
private InfoNode head= new InfoNode();
//添加节点
public void addNode(InfoNode infoNode) {
InfoNode temp = head;
while(true) {
if (temp.next==null) {
break;
}
temp=temp.next;
}
temp.next=infoNode;
}
//展示节点
public void showList() {
//判断头节点的指向是否为空,为空则直接返回
if (head.next==null) {
return;
}
InfoNode temp = head.next;
while(true) {
if (temp==null) {
break;
}
System.out.println(temp);
temp=temp.next;
}
}
//按照顺序添加
public void addByOrder(InfoNode infoNode) {
//判断头节点的指向是否为空,为空则将head.next指向infoNode
if (head.next==null) {
head.next=infoNode;
return;
}
InfoNode temp = head;
boolean flag = false;
while(true) {
//判断下一个节点是否为空,为空则说明没有找到匹配的插入位置,直接插入在最后
if (temp.next==null) {
temp.next=infoNode;
break;
}else if (temp.next.id > infoNode.id) {//若当前节点的下一个节点的id大于插入id,则将要插入的节点插入两者之间
InfoNode tmp = temp.next;
temp.next=infoNode;
infoNode.next=tmp;
break;
}else if (temp.next.id==infoNode.id) {//若有重复id的节点则表示节点已经存在,不能再插入
flag=true;
break;
}
temp=temp.next;
}
if (flag) {
System.out.println("该id已存在,添加失败");
}else {
System.out.println("添加成功!");
}
}
}
注:
public class DoubleLinkedList {
public DoubleInfoNode head = new DoubleInfoNode();
//添加节点
public void addNode(DoubleInfoNode newNode) {
if (head.next==null) {
head.next=newNode;
newNode.pre=head;
return;
}
DoubleInfoNode temp= head;
while(true) {
if (temp.next==null) {
temp.next=newNode;
newNode.pre=temp;
break;
}
temp=temp.next;
}
}
//删除节点
public void deleteNode(int id) {
if (head.next==null) {
System.out.println("双向链表为空");
return;
}
DoubleInfoNode temp= head;
while(true) {
if (temp.id==id) {
temp.pre.next=temp.next;
if (temp.next!=null) {
temp.next.pre=temp.pre;
}
System.out.println("删除成功");
break;
}
temp=temp.next;
}
}
//按顺序添加节点
public void addByOrder(DoubleInfoNode newNode) {
if (head.next==null) {
head.next=newNode;
newNode.pre=head;
return;
}
DoubleInfoNode temp=head;
boolean flag = false;
while(true) {
if (temp.next==null) {
temp.next=newNode;
newNode.pre=temp;
break;
}else if (temp.next.id > newNode.id) {
newNode.pre=temp;
newNode.next=temp.next;
temp.next=newNode;
newNode.next.pre=newNode;
break;
}else if (temp.next.id==newNode.id) {
flag=true;
break;
}
temp=temp.next;
}
if (flag) {
System.out.println("该id已存在,添加失败");
}else {
System.out.println("添加成功!");
}
}
//遍历节点
public void showList() {
if (head.next==null) {
return;
}
DoubleInfoNode temp = head.next;
while(true) {
if (temp==null) {
break;
}
System.out.println(temp);
temp=temp.next;
}
}
}
使用一个first指针记录开始节点
操作链表时,使用curNode指针记录当前指向节点
需要将最后一个节点的next指针指向first
遍历时循环的结束条件为curNode.next==first
/**
* 创建单向环形链表解决约瑟夫环问题
* @author dell
*
*/
public class CircleSingleLinkedList {
private InfoNode first = null;
//构建节点数为num的单向环形链表
public void addNode(int num) {
if (num<1) {
System.out.println("添加的节点必须大于等于1");
return;
}
InfoNode curNode = null;
for (int i = 1; i <= num; i++) {
InfoNode node = new InfoNode(i,"");
if (i==1) {
first=node;
first.next=first;
curNode=first;
}else {
curNode.next=node;
node.next=first;
curNode=node;
}
}
}
//显示当前单向环形列表的信息
public void showList() {
if (first==null) {
System.out.println("链表为空");
return;
}
InfoNode curNode = first;
while(true) {
System.out.println(curNode);
if (curNode.next==first) {
break;
}
curNode=curNode.next;
}
}
}
使用单向环形列表解决约瑟夫环问题
//约瑟夫问题解决
public void countNode(int startNum,int countNum,int nodeNum) {
if(startNum<1||countNum<1||nodeNum<1||startNum>nodeNum) {
System.out.println("数据输入不正确");
return;
}
addNode(nodeNum);
//定义helpNode并使helpNode指向最后一个节点
InfoNode helpNode = first;
while(true) {
if (helpNode.next==first) {
break;
}
helpNode=helpNode.next;
}
//将helpNode和first移动num-1个单位来满足题设
for (int i = 0; i < startNum-1; i++) {
helpNode=helpNode.next;
first=first.next;
}
while(true) {
if (helpNode==first) {
break;
}
//移动指针(数数过程)
for (int i = 0; i < countNum-1; i++) {
helpNode=helpNode.next;
first=first.next;
}
System.out.println(first);
first=first.next;
helpNode.next=first;
}
System.out.println(helpNode);
}
public class ArrayStack {
private int maxSize;
private int top;
private int[] stack;
//构造函数初始化属性值
public ArrayStack(int maxSize) {
this.maxSize=maxSize;
this.stack=new int[maxSize];
this.top=-1;
}
//判断是否为空
public boolean isEmpty() {
return top==-1;
}
//判断栈是否已满
public boolean isFull() {
return top==maxSize-1;
}
//入栈操作
public void push(int num) {
if (isFull()) {
System.out.println("栈满");
return;
}
this.top++;
this.stack[top]=num;
}
//出栈操作
public int pop() {
if (isEmpty()) {
throw new RuntimeException("栈为空");
}
return this.stack[top--];
}
//遍历并输出栈的信息
public void showStack() {
if (isEmpty()) {
System.out.println("栈空");
return;
}
for (int i = top; i >=0; i--) {
System.out.printf("stack[%d]=%d\n",i,stack[i]);
}
}
}
利用栈完成逆波兰表达式的计算(后缀表达式)
public class PolandNotation {
//将逆波兰表达式的运算字符串截取为String类型的List
private List<String> getStringList(String suffixExpression) {
List<String> list = new ArrayList<>();
String[] split = suffixExpression.split(" ");
for (String elem : split) {
list.add(elem);
}
return list;
}
public int calculate(String suffixExpression) {
//将表达式转为List
List<String> stringList = this.getStringList(suffixExpression);
//声明一个数字栈
Stack<String> numStack = new Stack<>();
for (String elem : stringList) {
//正则匹配:若匹配为数字,则入数字栈
if (elem.matches("\\d+")) {
numStack.push(elem);
}else { //否则为运算符,从栈顶弹出两个元素并进行相应的运算
int num1 = Integer.parseInt(numStack.pop());
int num2 = Integer.parseInt(numStack.pop());
int res = 0;
if (elem.equals("+")) {
res = num1 + num2;
} else if (elem.equals("*")) {
res = num1 * num2;
} else if (elem.equals("-")) {
res = num2 - num1;
} else if (elem.equals("/")) {
res = num2 / num1;
}else {
System.out.println("ERROR!");
}
//运算完成后将结果入数字栈
numStack.push("" + res);
}
}
//最后留在数字栈中的即为表达式运算结果
return Integer.parseInt(numStack.pop());
}
public static void main(String[] args) {
PolandNotation polandNotation = new PolandNotation();
int calculate = polandNotation.calculate("3 4 + 5 * 7 /");
System.out.println(calculate);
}
}
public class HashTableDemo {
class Emp{
public int id;
public String name;
public Emp next;
public Emp(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
class EmpLinkedList{
private Emp head;
public void add(Emp emp) {
if (head == null) {
head = emp;
return;
}
Emp temp = head;
while (true) {
if (temp.next == null) {
temp.next = emp;
break;
}
temp = temp.next;
}
}
public void list() {
Emp temp = head;
while (true) {
if (temp == null) {
break;
}
System.out.println(temp);
temp = temp.next;
}
}
}
class HashTab{
//链表数组,使用哈希散列函数进行不同特征值的映射
EmpLinkedList[] lists;
int size;
public HashTab(int size) {
this.size = size;
this.lists = new EmpLinkedList[size];
//注意此处应该将数组链表中的元素初始化,否则后续操作会出现空指针异常
for (int i = 0; i < size; i++) {
lists[i] = new EmpLinkedList();
}
}
public void add(Emp emp) {
if (emp == null) {
return;
}
int listNum = hashFun(emp.id);
lists[listNum].add(emp);
}
public void list() {
for (int i = 0; i < lists.length; i++) {
lists[i].list();
}
}
//这里散列函数为演示方便为简单的取模运算,决定不同的特征值元素在哪个链表中
public int hashFun(int id) {
return id % size;
}
}
}