原始数组与稀疏数组的转换
复习数据结构第一天~~~~
public class SparseArray {
public static void main(String[] args) {
int[][] arr = new int[10][10];
arr[2][3] = 1;
arr[1][3] = 3;
arr[2][2] = 5;
arr[7][3] = 98;
arr[9][7] = 6;
printArr(arr);
System.out.println("========================");
int[][] spr = toSparseArray(arr);
printArr(toInitialArray(spr));
}
public static int[][] toInitialArray(int[][] spr) {
int[][] arr = new int[spr[0][0]][spr[0][1]];
for (int i = 0; i < spr[0][2]; i++) {
arr[spr[i + 1][0]][spr[i + 1][1]] = spr[i + 1][2];
}
return arr;
}
/**
* @param arr 原数组
* 第一行 原数组的两维的大小,第三列代表总共有多少非零数据
*/
public static int[][] toSparseArray(int[][] arr) {
int count = 0; // 记录原数组有多少个非零数据
for(int[] row: arr){
for(int ele: row) if(ele != 0) count ++;
}
int[][] sparseArr = new int[count + 1][3]; // 定义存放的稀疏数组
sparseArr[0][0] = arr.length;
sparseArr[0][1] = arr[0].length;
sparseArr[0][2] = count;
count = 0;
for(int i = 0; i < sparseArr[0][0]; i ++) {
for (int j = 0; j < sparseArr[0][1]; j++) {
if(arr[i][j] != 0) {
++ count;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = arr[i][j];
}
}
}
return sparseArr;
}
public static void printArr(int[][] arr) {
for(int[] row: arr){
for(int ele: row) System.out.print(ele + " ");
System.out.println();
}
}
}
数组模拟队列及循环队列实现
public class ArrayQue {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
CircleQueArr queueArr = new CircleQueArr(4);
String key = "";
int ele;
boolean loop = true;
while(loop) {
System.out.println("请输入你想执行的操作:");
System.out.println("push:(pu");
System.out.println("pop:(po");
System.out.println("peek:(pe");
System.out.println("showData:(sh");
System.out.println("exit:(ex");
key = scanner.next();
switch(key) {
case "pu":
System.out.println("请输入你想放入队列的数: ");
ele = scanner.nextInt();
queueArr.push(ele);
break;
case "po":
System.out.println(queueArr.pop());
break;
case "pe":
System.out.println(queueArr.peek());
break;
case "sh":
queueArr.showData();
break;
case "ex":
scanner.close();
loop = false;
break;
default:
break;
}
}
}
}
class QueueArr {
private int[] arr;
private int maxSize; // 队列的最大长度
private int front;
private int rear;
public QueueArr(int maxSize) {
this.arr = new int[maxSize];
this.maxSize = maxSize;
this.front = -1;
this.rear = -1;
}
public boolean isEmpty() {
return rear == front;
}
public boolean isFull() {
return rear == maxSize - 1;
}
public void push(int ele) {
if(isFull()) {System.out.println("队列已满~~"); return;}
arr[++ rear] = ele;
}
public int pop() {
if(isEmpty()) throw new RuntimeException("队列为空,无法取数据~~");
return arr[++ front];
}
public int peek() {
if(isEmpty()) throw new RuntimeException("队列为空,顶端没有数据~~");
return arr[front + 1];
}
public void showData() {
if(isEmpty()) {
System.out.println("队列为空,没有数据可show~~");
return;
}
for (int i = front; i < rear; i++) {
System.out.printf("arr[%d] = %d \t", i + 1, arr[i + 1]);
}
System.out.println();
}
}
class CircleQueArr {
private int[] arr;
private int maxSize;
private int front; // 指向头部的前一个位置
private int rear; // 指向队列的尾部,没有元素时与front相等
public CircleQueArr(int maxSize) {
arr = new int[maxSize];
this.maxSize = maxSize;
front = rear = -1;
}
public boolean isEmpty() {
return front == rear;
}
public boolean isFull() {
return (front + maxSize - 1) % maxSize == rear;
}
public void push(int ele) {
if(isFull()) {
System.out.println("队列已满,无法加入新数据~~");
return;
}
rear = (rear + 1) % maxSize;
arr[rear] = ele;
}
public int size() {
return (rear + maxSize - front) % maxSize;
}
public int pop() {
if(isEmpty()) throw new RuntimeException("队列中没有元素,无法弹出~~");
front = (front + 1) % maxSize;
return arr[front];
}
public void showData() {
if(isEmpty()) {
System.out.println("队列中没有数据,无法show~~");
return;
}
int index = front;
for (int i = 0; i < size(); i++) {
index = (index + 1) % maxSize;
System.out.printf("arr[%d] = %d\t", index, arr[index]);
}
System.out.println();
}
public int peek() {
if(isEmpty()) throw new RuntimeException("没有数据,无法peek顶端元素~~");
return arr[(front + 1) % maxSize];
}
}
单链表增删改及常见反转问题,删除倒数第k个节点等问题多种方法实现
public class SingleLinkedList {
@SuppressWarnings({"all"})
public static void main(String[] args) {
LinkedListS linked = new LinkedListS();
LinkedListS linked1 = new LinkedListS();
SNode sNode8 = new SNode(8);
SNode sNode2 = new SNode(2);
SNode sNode3 = new SNode(3);
SNode sNode4 = new SNode(4);
SNode sNode6 = new SNode(6);
SNode sNode1 = new SNode(1);
SNode sNode0 = new SNode(0);
SNode sNode7 = new SNode(7);
SNode sNode9 = new SNode(9);
SNode sNode10 = new SNode(10);
SNode sNode11 = new SNode(11);
linked.addNodeByValue(sNode4);
linked.addNodeByValue(sNode2);
linked.addNodeByValue(sNode3);
linked.addNodeByValue(sNode8);
linked.addNodeByValue(sNode6);
linked1.addNodeByValue(sNode1);
linked1.addNodeByValue(sNode0);
linked1.addNodeByValue(sNode7);
linked1.addNodeByValue(sNode9);
linked1.addNodeByValue(sNode10);
linked1.addNodeByValue(sNode11);
linked1.showList();
linked1.reverseLinkedList1();
System.out.println("===========");
linked1.showList();
// System.out.println(linked.getHead());
// linked1.showList();
// linked1.mergeOrderLinkedLists(linked.getHead());
// System.out.println("===========");
// linked1.showList();
// System.out.println(linked1.size());
}
}
class LinkedListS {
private SNode head; // 该链表没有dummyHead头
//合并两个有序的单链表到当前调用该方法的对象中
public void mergeOrderLinkedLists(SNode dummy) {
if(head == null || dummy == null) {
head = (head == null)?dummy:head;
return;
}
SNode cur1 = head;
SNode cur2 = dummy;
SNode newDummyHead = new SNode(-1);
SNode cur = newDummyHead;
while(cur1 != null && cur2 != null) {
if(cur1.getValue() > cur2.getValue()) {
cur.setNext(cur2);
cur2 = cur2.getNext();
}
else {
cur.setNext(cur1);
cur1 = cur1.getNext();
}
cur = cur.getNext();
}
cur.setNext(cur1 == null ?cur2:cur1);
head = newDummyHead.getNext();
}
//反转单链表1
public void reverseLinkedList1() {
/**
* 每遍历一个节点就将这个节点放在新链表的头部
*/
if(head == null || head.getNext() == null) return;
SNode newHead = new SNode(-1), cur = head;
SNode next; // 保存cur的下一个节点
while(cur != null) {
next = cur.getNext();
cur.setNext(newHead.getNext());
newHead.setNext(cur);
cur = next;
}
head = newHead.getNext();
}
//反转单链表
public void reverseLinkedList() {
if(head == null || head.getNext() == null) {
System.out.println("链表为空或者链表只有一个节点~~返回");
return;
}
//比如2->3->4->5这条链表,那么先当前指向2,用一个next指向3,让2的next为空,3的next保存为next1
//让3的next指向2,所有变量往后移动一个节点
SNode pre = head;
SNode next = head.getNext();
head.setNext(null);
SNode temp;
while(next.getNext() != null) {
temp = next.getNext();
next.setNext(pre);
pre = next;
next = temp;
}
next.setNext(pre);
head = next;
}
//删除单链表的倒数第k个节点,用快慢指针,不调用内部删除的方法
public void delLastK1(int k) {
if(k > size() || k < 1) {
System.out.println("输入的k有误~~");
return;
}
//额外创建一个节点指向头部
SNode dummyHead = new SNode(-1);
dummyHead.setNext(head);
SNode fast, slow;
fast = slow = dummyHead;
//先让快指针走k步,再同时走,当发现快指针已经是最后的一个节点时,慢指针的下一个节点即是需要删除的节点
int count = 0; // 记录快指针走的步数
while(count != k) {
fast = fast.getNext();
count ++;
}
while(fast.getNext() != null) {
fast = fast.getNext();
slow = slow.getNext();
}
//那么slow的下一个节点就是要删除的
slow.setNext(slow.getNext().getNext());
head = dummyHead.getNext();
}
//删除单链表的倒数第k个节点,下面两种方法类似
public void delLastK(int k) {
if(k > size() || k < 1) {
System.out.println("输入的k有误~~");
return;
}
//方法1:倒数第k个即为正数第size() - k + 1个,那么遍历即可
//方法2:利用链表的反转进行删除第k个节点
reverseLinkedList();
int index = 1;
SNode cur = head;
while(index != k){
cur = cur.getNext();
index ++;
}
delNode(cur.getValue());
reverseLinkedList();
}
//返回该单链表的长度
public int size() {
if(head == null) return 0;
SNode cur = head;
int count = 1;
while(cur.getNext() != null) {
count ++;
cur = cur.getNext();
}
return count;
}
//删除链表的某个节点,传入的是相应的值
public void delNode(int value) {
if(head == null) {
System.out.println("链表为空,没有节点可删除~~");
return;
}
if(head.getValue() == value) { // 删除的是头节点
head = head.getNext();
return;
}
SNode cur = head;
while(cur.getNext() != null) {
if(cur.getNext().getValue() == value) break;
cur = cur.getNext();
}
if(cur.getNext() == null) { // 没有找到对应要删除的节点
System.out.println("没有找到对应要删除的节点~~");
return;
}
cur.setNext(cur.getNext().getNext());
}
//给链表按照value值从小到大添加元素
public void addNodeByValue(SNode sNode) {
if(head == null) {
head = sNode;
return;
}
if(sNode.getValue() < head.getValue()) {
sNode.setNext(head);
head = sNode;
return;
}
SNode cur = head;
while(cur.getNext() != null) {
if(cur.getNext().getValue() <= sNode.getValue()) cur = cur.getNext();
else break;
}
sNode.setNext(cur.getNext());
cur.setNext(sNode);
}
public SNode getHead() {
return head;
}
//给链表直接往尾部添加元素
public void addNode(SNode sNode) {
if(head == null) {
head = sNode;
return;
}
SNode cur = head;
while(cur.getNext() != null) {
cur = cur.getNext();
}
cur.setNext(sNode);
}
//遍历链表
public void showList() {
if(head == null) {
System.out.println("链表为空,没有元素可遍历~~");
return;
}
SNode cur = head;
while(cur != null) {
System.out.println(cur);
cur = cur.getNext();
}
}
}
class SNode {
private int value;
private SNode next;
@Override
public String toString() {
return "SNode{" +
"value=" + value +
'}';
}
public SNode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public SNode getNext() {
return next;
}
public void setNext(SNode next) {
this.next = next;
}
}
双向链表的常见操作实现
public class DoubleLinkedListDemo {
public static void main(String[] args) {
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
SNode sNode8 = new SNode(8);
SNode sNode2 = new SNode(2);
SNode sNode3 = new SNode(3);
SNode sNode4 = new SNode(4);
SNode sNode6 = new SNode(6);
doubleLinkedList.addNodeByOrder(sNode8);
doubleLinkedList.addNodeByOrder(sNode2);
doubleLinkedList.addNodeByOrder(sNode3);
doubleLinkedList.addNodeByOrder(sNode4);
doubleLinkedList.addNodeByOrder(sNode6);
doubleLinkedList.showList();
System.out.println("====================");
doubleLinkedList.delNodeByValue(2);
doubleLinkedList.showList();
}
}
class DoubleLinkedList {
private SNode head;
//删除某个节点
public void delNodeByValue(int value) {
if(head == null) {
System.out.println("链表为空,没有节点可删除~~");
return;
}
if(head.getValue() == value) { // 删除的是头节点
head = head.getNext();
head.setPre(null);
return;
}
SNode cur = head.getNext();
while(cur != null) {
if(cur.getValue() == value) break;
cur = cur.getNext();
}
if(cur != null) { // 代表找到了这个要删除的节点
cur.getPre().setNext(cur.getNext());
if(cur.getNext() != null) cur.getNext().setPre(cur.getPre());
}
}
//增,有序,从小到大,与单链表一样
public void addNodeByOrder(SNode sNode) {
if(head == null) {
head = sNode;
return;
}
if(sNode.getValue() < head.getValue()) {
sNode.setNext(head);
head.setPre(sNode);
head = sNode;
return;
}
SNode cur = head;
while(cur.getNext() != null) {
if(cur.getNext().getValue() <= sNode.getValue()) cur = cur.getNext();
else break;
}
sNode.setNext(cur.getNext());
sNode.setPre(cur);
if(cur.getNext() != null) cur.getNext().setPre(sNode);
cur.setNext(sNode);
}
//增,无序
public void addNode(SNode sNode) {
if(head == null) {
head = sNode;
return;
}
SNode cur = head;
while(cur.getNext() != null) {
cur = cur.getNext();
}
cur.setNext(sNode);
sNode.setPre(cur);
}
public void showList() {
if(head == null) {
System.out.println("链表为空,没有元素可遍历~~");
return;
}
SNode cur = head;
while(cur != null) {
System.out.println(cur);
cur = cur.getNext();
}
}
}
class SNode {
private int value;
private SNode next;
private SNode pre;
public SNode getPre() {
return pre;
}
public void setPre(SNode pre) {
this.pre = pre;
}
@Override
public String toString() {
return "SNode{" +
"value=" + value +
'}';
}
public SNode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public SNode getNext() {
return next;
}
public void setNext(SNode next) {
this.next = next;
}
}
循环单链表解决约瑟夫问题实现
public class CircleLinkedListDemo {
static List<Integer> list = new ArrayList<>();
public static void main(String[] args) {
CircleLinkedList circleLinkedList = new CircleLinkedList();
SNode sNode1 = new SNode(1);
SNode sNode2 = new SNode(2);
SNode sNode3 = new SNode(3);
SNode sNode4 = new SNode(4);
SNode sNode5 = new SNode(5);
SNode sNode6 = new SNode(6);
SNode sNode7 = new SNode(7);
SNode sNode8 = new SNode(8);
circleLinkedList.addNode(sNode1);
circleLinkedList.addNode(sNode2);
circleLinkedList.addNode(sNode3);
circleLinkedList.addNode(sNode4);
circleLinkedList.addNode(sNode5);
circleLinkedList.addNode(sNode6);
circleLinkedList.addNode(sNode7);
circleLinkedList.addNode(sNode8);
circleLinkedList.showList();
System.out.println("=======================");
// System.out.println("=====删除的节点值是=====" + circleLinkedList.delNode(sNode4));
jpf(circleLinkedList.getHead(), 5, 6);
System.out.println(list);
}
//用该循环链表解决约瑟夫问题
/**
* @param sNode 这是循环链表的头节点
* @param k 这是从该循环链表的第几个人开始数数
* @param m 这是代表数到几的那个人退出队列
* @return 返回的是最终退出队列的顺序
*/
public static void jpf(SNode sNode, int k, int m) {
int index = 1;
SNode cur = sNode;
while(index != k) {
cur = cur.getNext();
index ++;
}
countNum(cur, m);
}
/**
* @param sNode 这是循环链表起始数数的节点
* @param m 数到几则退出
* @return 退出的那个人的value,即编号
*/
public static void countNum(SNode sNode, int m) { // 用递归实现,使用双指针会更简单~~
if(sNode == null) return;
if(sNode.getNext() == sNode) {
list.add(sNode.getValue());
return;
}
//可以将删除节点的方法写在这里
int count = 1;
SNode cur = sNode;
while(count != m) {
cur = cur.getNext();
count ++;
}
//此时cur是等待删除的那个节点
list.add(cur.getValue());
//删除cur节点,找到cur的上一个节点
SNode temp = cur;
while(temp.getNext() != cur) {
temp = temp.getNext();
}
temp.setNext(cur.getNext());
countNum(temp.getNext(), m);
}
}
class CircleLinkedList { // 循环链表
private SNode head;
public SNode getHead() {
return head;
}
//删除该链表的某个节点并返回这个值
public int delNode(SNode sNode) {
if(head == null) {
throw new RuntimeException("链表为空,无法删除~~");
}
SNode cur = head;
if(head.getValue() == sNode.getValue()) { // 删除的是头节点,那么要拿到这条链表的尾节点
while(cur.getNext() != head) {
cur = cur.getNext();
}
//此时cur是尾巴节点
if(cur == head) {
head = null;
return sNode.getValue();
}
head = head.getNext();
cur.setNext(head);
return sNode.getValue();
}
// 如果删除的不是头节点,那么也要找到待删除节点的头一个节点
cur = head;
while(cur.getNext().getValue() != sNode.getValue()) {
cur = cur.getNext();
}
cur.setNext(cur.getNext().getNext());
return sNode.getValue();
}
//遍历该循环链表
public void showList() {
if(head == null) {
System.out.println("该循环链表为空,无法遍历~~");
return;
}
SNode cur = head;
System.out.println(head);
while(cur.getNext() != head) {
System.out.println(cur.getNext());
cur = cur.getNext();
}
}
//添加元素
public void addNode(SNode sNode) {
if(head == null) {
head = sNode;
head.setNext(head);
return;
}
SNode cur = head;
while(cur.getNext() != head) {
cur = cur.getNext();
}
cur.setNext(sNode);
sNode.setNext(head);
}
}
class SNode {
private int value;
private SNode next;
@Override
public String toString() {
return "SNode{" +
"value=" + value +
'}';
}
public SNode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public SNode getNext() {
return next;
}
public void setNext(SNode next) {
this.next = next;
}
}
以上仅作为个人复习用,如果需要改进之处,欢迎提出~~