一. 队列
1. 队列的数组实现
因为要考虑复用问题,所以要实现循环队列,思路如下
(rear == front不能判断队列是空还是满,所以考虑牺牲一个空间)
(1). front:指向队列的第一个元素,初始值为0
(2).rear:指向队列最后一个元素的后一个位置,初始值为0
(3).当队列空时,rear == front
(4).当队列满时:(rear+1)%maxsize == front
(5).队列中元素个数:(rear+maxsize-front)%maxsize
public class ArrayQueue {
private int maxSize;
private int front;//指向第一个元素
private int rear; //指向最后一个元素的下一个位置
private int[] arr;
public ArrayQueue(int maxSize){
this.maxSize = maxSize;
arr = new int[maxSize];
front = 0;
rear = 0;
}
//判断队列是否为空
public boolean isEmpty(){
return front == rear;
}
//判断队列是否满
public boolean isFull(){
return (rear+1)%maxSize == front;
}
//队列中元素的个数
public int getNum(){
return (rear+maxSize-front)%maxSize;
}
//取出队列的首元素
public int pop(){
if(isEmpty()){
throw new RuntimeException("队列为空");
}
int result = arr[front];
front = (front+1)%maxSize;
return result;
}
//添加元素到队列中
public void add(int value){
if (isFull()){
throw new RuntimeException("队列已满");
}
arr[rear] = value;
rear = (rear+1)%maxSize;
}
//查看队列的第一个元素
public int peek(){
if (isEmpty()){
throw new RuntimeException("队列为空");
}
return arr[front];
}
//查看队列中的所有元素
public void getAll(){
if (isEmpty()){
throw new RuntimeException("队列为空");
}
for (int i = front; i < front+getNum(); i++){
System.out.print(arr[i]+ " ");
}
}
}
二. 单链表
1. 单链表的实现
public class SingleLinkedList {
private Node head = new Node(0,"");
//添加节点
public void add(Node node){
Node temp = head;
while (temp.next != null){
temp = temp.next;
}
temp.next = node;
}
//遍历链表
public void list(){
if (head.next == null){
System.out.println("链表为空");
return;
}
Node temp = head;
while (true){
System.out.println(temp);
if (temp.next == null){
return;
}
temp = temp.next;
}
}
//按顺序添加元素
public void addByOrder(Node node){
Node temp = head;
while (true){
if (temp.next == null){
break;
}
if (node.no == temp.no){
throw new RuntimeException("该编号已经存在");
}
if (temp.next.no > node.no){
break;
}
temp = temp.next;
}
node.next = temp.next;
temp.next =node;
}
//删除节点
public void remove(int no){
Node temp = head;
while (true){
if (temp.next == null){
throw new RuntimeException("未找到该元素");
}
if (temp.next.no == no){
break;
}
temp = temp.next;
}
temp.next = temp.next.next;
}
}
class Node{
public int no;
public String name;
public Node next;
public Node(int no,String name){
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Node{" +
"no=" + no +
", name='" + name + '\'' +
", next=" + next +
'}';
}
}
2. 单链表的反转
(1).递归实现
public Node reverse(Node head) {
if (head == null || head.next == null)
return head;
Node temp = head.next;
Node newHead = reverse(head.next);
temp.next = head;
head.next = null;
return newHead;
}
(2).遍历实现
blic static Node reverseList(Node node) {
Node pre = null;
Node next = null;
while (node != null) {
next = node.next;
node.next = pre;
pre = node;
node = next;
}
return pre;
}
3. 双向链表的实现
public class DoubleLinkedList {
DoubleNode head = new DoubleNode(0);
//遍历,修改同单向链表
//添加双向链表
public void add(DoubleNode node){
DoubleNode temp = head;
while (temp.next != null){
temp = temp.next;
}
temp.next = node;
node.pre = temp;
}
//删除节点
public void remove(int data){
DoubleNode temp = head;
while (true){
if (temp == null){
throw new RuntimeException("未找到该元素");
}
if (temp.data == data){
break;
}
temp = temp.next;
}
if (temp.next != null){
temp.next.pre = temp.pre;
}
temp.pre.next = temp.next;
}
//遍历链表
public void list(){
if (head.next == null){
System.out.println("链表为空");
return;
}
DoubleNode temp = head;
while (true){
System.out.println(temp.data);
if (temp.next == null){
return;
}
temp = temp.next;
}
}
}
4. 约瑟夫问题(循环链表)
/*
* 约瑟夫问题
*/
public class CircleLinkedList {
public static void main(String[] args) {
CircleLinkedList circleLinkedList = new CircleLinkedList();
circleLinkedList.addNode(5);
circleLinkedList.countBoy(1,2,5);
}
private DoubleNode first = new DoubleNode(-1);
//环形链表创建
private void addNode(int nums){
if (nums < 1){
System.out.println("编号不正确");
return;
}
DoubleNode cur = null;//辅助指针
for (int i=1; i <= nums; i++){
DoubleNode boy = new DoubleNode(i);
if (i == 1){
first = boy;
//构成环状
first.next = first;
cur = first;
}else {
cur.next = boy;
boy.next = first;
cur = boy;
}
}
}
//打印环形链表
public void show(){
if (first == null){
System.out.println("链表为空");
}
DoubleNode cur = first;
while (true){
System.out.println(cur.data+" ");
if (cur.next == first)break;
cur = cur.next;
}
}
//根据用户输入计算出小孩出圈顺序
//从第startNo个小孩开始数数
//countNum表示数几下
//nums表示有几个小孩在圈中
public void countBoy(int startNum, int countNum, int nums){
if (first == null || startNum < 1 ||startNum > nums){
System.out.println("参数输入有误");
}
//创建一个辅助指针,指向first的前一个节点
DoubleNode helper = first;
while (true){
if (helper.next == first)break;
helper = helper.next;
}
//报数开始前,先让first和helper移动到指定的位置
for (int i = 0; i < startNum-1; i++){
first = first.next;
helper = helper.next;
}
while (true){
if (helper == first)break;
//让helper和first同时移动count-1.此时first指向的节点就是要出圈的小孩
for(int j = 0; j < countNum-1; j++){
first = first.next;
helper = helper.next;
}
System.out.print(first.data+" ");
first = first.next;
helper.next = first;
}
System.out.print(first.data+" ");
}
}
三. 栈
1. 栈的数组实现
public class ArrayStack {
private int top = -1;
private int[] array;
private int maxSize;
public ArrayStack(int maxSize){
this.maxSize = maxSize;
array = new int[maxSize];
}
//判满
public boolean isFull(){
if (top == maxSize-1){
return true;
}
return false;
}
//判空
public boolean isEmpty(){
if (top == -1){
return true;
}
return false;
}
//入栈
public void push(int a){
if (isFull()){
System.out.println("栈满");
return;
}
array[++top] = a;
}
//出栈
public int pop(){
if (isEmpty()){
throw new RuntimeException("栈空");
}
int number = array[top];
top--;
return number;
}
//遍历栈
public void list(){
if (isEmpty())return;
while (top != -1){
System.out.print(array[top]+" ");
top--;
}
}
}