文章目录
一、线性结构
1.1顺序存储(开辟一组连续的空间存储数据)
1.1.1线性表
1. Java内置数组的优点
① 数组一旦创建不能改变
int[] arr1 = new int [5]; //创建5个默认值为0的数组
int[] arr2 = new int[]{1,2,3,4,5}; //创建五个赋初始值的数组
②数组只能存储同一类型的数据
double[] arr3 = new double[5]; //可以存储全int或者全double类型的数据,向下兼容
③数组中每个存储空间地址连续且相等
如果要插入一个元素或者删除一个元素,那么后面的元素必须往前挪或者往后挪
④数组提供角标式访问元素
2. Java内置数组的缺点
①长度不可变,容量不够怎么办
容量不够,那就扩容,比如创建原来数组的几倍长度,然后复制地址指向新数组,原先数组被垃圾回收
②地址连续要提供角标访问很快,但增删元素怎么办
不管增还是删,都要动其他元素,总是要考虑最坏情况
③数组只有length这个属性,没有其他方法
size即表示数据的有效个数,也表示新元素要进入的位置
3. 为什么要调用动态数组
动态数组是顺序存储结构具体实现的核心思想
4. 线性表的定义
零个或多个元素的有限序列
a(i-1)是ai的直接前驱
a (i+1)是ai的直接后继
线性表长度是线性表的有效个数size
抽象类里面所有的方法都没有实现,都是抽象的,那么这个抽象类就可以写成接口
写成接口还有个好处就是防止代码冗余
并且写接口要符合社会现实世界
5.List接口的定义

6.List接口的代码的实现(代码)
package p1.接口;
public interface List<E> extends Iterable {
//在默认表尾添加一个元素
public void add(E element);
//在指定角标处添加元素
public void add(int index,E element);
//删除指定元素
public void remove(E element);
//删除指定角标处的元素,并返回原先的值
public E remove(int index);
//获取指定角标处的元素
public E get(int index);
//修改指定角标index的值为element,并返回原先的值
public E set(int index,E element);
//获取线性表中的元素的个数
public int size();
//查看元素角标第一次出现的位置(从左到右)
public int indexOf(E element);
//判断是否包含元素
public boolean contains(E element);
//判断线性表是否为空
public boolean isEmpty();
//清空线性表
public void clear();
//按照比较器的内容进行排序
public void sort(Comparable<E> c);
//在原线性表中获取一个子线性表,原线性表[fromIndex,toIndex]这个部分
public List<E> subList(int fromIndex,int toIndex);
}
7.线性表的实现ArrayList(代码)
ArrayList就是线性结构顺序存储方式的具体实现,称为线性表

创建ArrayList类实现List接口
定义相关成员属性和构造函数
package p2.线性结构;
import p1.接口.List;
import java.util.Comparator;
import java.util.Iterator;
//自定义的线性表的顺序存储方式
public class ArrayList<E> implements List<E> {
//数组的容器 data.length 指的就是当前数组的容量
private E[] data;
//元素的个数size == 0线性表为空 size == data.length 线性表满了
//size 新元素默认尾部添加时要去的角标
private int size;
//默认容量
private static int DEFAULT_CAPACITY= 10;
//默认构造函数:创建一个默认容量为10的线性表
public ArrayList() {
this(DEFAULT_CAPACITY);
}
public ArrayList(int capacity) {
if(capacity<0){
throw new IllegalArgumentException("capacity must > 0");
}
DEFAULT_CAPACITY = capacity;
data = (E[]) new Object[DEFAULT_CAPACITY];
size = 0;
}
//指定数组的构造函数:传入一个数组,将该数组封装成一个线性表
public ArrayList(E[] arr){
if(arr == null || arr.length == 0){
throw new IllegalArgumentException("arr can not be null");
}
data = (E[]) new Object[DEFAULT_CAPACITY];
for(int i = 0 ; i < arr.length ; i++){
add(arr[i]);
}
}
@Override
public void add(E element) {
add(size,element);
}
@Override
public void add(int index, E element) {
if(index < 0 || index > size ){
throw new IllegalArgumentException("add index out of range");
}
//判断线性表是否为满的状态
if(size==data.length){
resize(2 * data.length);
}
//向后移动元素
for(int i = size -1 ;i >= index ;i--){
data[i+1] = data[i];
}
//将新元素插入到指定位置
data[index] = element;
size++;
}
//扩容/缩容操作 不应该向外提供
private void resize(int newLen) {
E[] newData = (E[]) new Object[newLen];
for(int i = 0; i< size;i++){
newData[i] = data[i];
}
data = newData;
}
@Override
public void remove(E element) {
int index = indexOf(element);
if(index != -1){
remove(index);
}
}
@Override
public E remove(int index) {
if(index < 0 || index >=size){
throw new IllegalArgumentException("remove index out of range");
}
//先保存要删除的值
E ret=data[index];
//移动元素
for(int i = index+1;i <size; i ++ ){
data[i-1] = data[i];
}
size--;
//什么时候缩容
//1.有效元素是容量的1/4
//2.当前容量不得小于等于默认容量
if(size == data.length /4 && data.length >DEFAULT_CAPACITY){
resize(data.length/2);
}
return ret;
}
@Override
public E get(int index) {
if(index < 0 || index>size){
throw new IllegalArgumentException("get index out of range");
}
return data[index];
}
@Override
public E set(int index, E element) {
if(index < 0|| index >= size){
throw new IllegalArgumentException("set index out of range");
}
E ret = data[index];
data[index]= element;
return ret;
}
@Override
public int size() {
return size;
}
//额外添加一个函数,获取线性表中哪个数组的容量
private int getCapacity(){
return data.length;
}
@Override
public int indexOf(E element) {
/*
== 比的是啥?主要看等号的两边是啥
== 两边是基本数据类型的话 比的是值
byte short int long
float double
char boolean
== 两边是引用数据类型的话 比的是地址
数组 字符串 其他的类对象
*/
for(int i =0;i < size;i++){
if(data[i].equals(element)){
return i;
}
}
return -1;
}
@Override
public boolean contains(E element) {
return indexOf(element) != -1;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void clear() {
data = (E[]) new Object[DEFAULT_CAPACITY];
size = 0;
}
@Override
public void sort(Comparator<E> c) {
if (c == null) {
throw new IllegalArgumentException("comparator can not be null");
}
for (int i = 1; i < size; i++) {
E e = data[i];
int j = 0;
for (j = i; j > 0 && c.compare(data[j - 1], e) > 0; j--) {
data[j] = data[j - 1];
}
data[j] = e;
}
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
if (fromIndex < 0 || toIndex >= size || fromIndex > toIndex) {
throw new IllegalArgumentException("must 0 <= fromIndex <= toIndex <= size - 1");
}
ArrayList<E> list = new ArrayList<>();
for (int i = fromIndex; i <= toIndex; i++) {
list.add(data[i]);
}
return list;
}
@Override
public boolean equals(Object o) {
//1.判空
if (o == null) {
return false;
}
//2.判自己
if (this == o) {
return true;
}
//3.判类型
if (o instanceof ArrayList) {
//4.按照自己的逻辑进行比较
ArrayList<E> other = (ArrayList<E>) o;
//5.先比有效元素的个数
if (size != other.size) {
return false;
}
//6.有效元素个数相等的情况下 逐个比较元素
for (int i = 0; i < size; i++) {
if (!data[i].equals(other.data[i])) {
return false;
}
}
return true;
}
return false;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
if (isEmpty()) {
sb.append(']');
} else {
for (int i = 0; i < size; i++) {
sb.append(data[i]);
if (i == size - 1) {
sb.append(']');
} else {
sb.append(',');
sb.append(' ');
}
}
}
return sb.toString();
}
@Override
public Iterator iterator() {
return new ArrayListIterator();
}
//创建一个属于ArrayList的迭代器
class ArrayListIterator implements Iterator<E> {
private int cur = 0;
@Override
public boolean hasNext() {//判断是否有下一个元素
return cur < size;
}
@Override
public E next() {//如果有下一个元素 则把当前元素返回 并移至到下一个元素
return data[cur++];
}
}
}
8.TestArrayList测试类(代码)
package p0.测试;
import p2.线性结构.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Random;
public class TestArrayList {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
System.out.println(list);
Random random = new Random();
for(int i = 0; i < 10;i++){
list.add(random.nextInt(100));
}
System.out.println(list);
for (int i = 0; i< 10;i++){
list.add(0,i);
}
System.out.println(list);
System.out.println(list.size());
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 -o2;
}
});
System.out.println(list);
for(Object nums : list){
System.out.println(nums);
}
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next()+" ");
}
}
}
1.1.2栈
1.栈的定义
①栈是限定仅在表尾进行插入和删除操作的线性表
②我们把允许插入和删除的一端称为栈顶,另一端称为栈底
③不含任何数据元素的栈称为空栈
④栈又称为后进先出的线性表,简称LIFO结构
⑤线性表是一个线性表,其数据元素具有线性关系,只不过它是一种特殊的线性表而已
⑥栈的插入操作,叫做进栈,也称压栈、入栈
⑦栈的删除操作,叫做出栈,也称弹栈
2.Stack栈接口的定义

3.Stack栈接口的实现(代码)
package p1.接口;
public interface Stack<E> extends Iterable<E> {
public int size();
public boolean isEmpty();
public void push(E element);
public E pop();
public E peek();
public void clear();
}
4.ArrayStack的实现(代码)
package p2.线性结构;
import p1.接口.Stack;
import javax.swing.*;
import java.util.Iterator;
import java.util.Objects;
public class ArrayStack<E> implements Stack<E> {
private ArrayList<E> list;
public ArrayStack(){
list = new ArrayList<>();
}
public ArrayStack(int capacity){
list = new ArrayList<>(capacity);
}
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void push(E element) {
list.add(element);
}
@Override
public E pop() {
return list.remove(list.size()-1);
}
@Override
public E peek() {
return list.get(list.size()-1);
}
@Override
public void clear() {
list.clear();
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public String toString() {
return list.toString();
}
@Override
public boolean equals(Object o) {
if(o == null){
return false;
}
if(this == o){
return true;
}
if( o instanceof ArrayStack){
ArrayStack other = (ArrayStack) o;
return this.list.equals(other.list);
}
return false;
}
}
5. TestArrayStack的测试(代码)
package p0.测试;
import p2.线性结构.ArrayStack;
public class TestArrayStack {
public static void main(String[] args) {
ArrayStack<Integer> stack01 = new ArrayStack<>();
ArrayStack<Integer> stack02 = new ArrayStack<>(15);
for(int i = 1;i <=12 ;i++){
stack01.push(i);
stack02.push(i);
}
System.out.println(stack01);
System.out.println(stack02);
System.out.println(stack01.equals(stack02));
System.out.println(stack01.pop());
System.out.println(stack01);
System.out.println(stack01.peek());
}
}
6. 中缀表达式(代码)
package p2.线性结构;
/**
* 飘飘豆芽
*/
public class InfixCalculator4 {//中缀表达式计算器
public static void main(String[] args) {
String s = "(10+20/2*3)/2+8";
//拆分目标( 10 + 20 / 2 * 3 )/ 2 + 8
//直接拆 ( 1 0 + 2 0 / 2 * 3 ) / 2 + 8
int i = evaluateEpression(s);
System.out.println("(10+20/2*3)/2+8="+i);
}
private static int evaluateEpression(String s) {
ArrayStack<Character> operatorStack = new ArrayStack<>();
ArrayStack<Integer> numberStack = new ArrayStack<>();
String s1 = insertBlanks(s);
String []tokens = s1.split(" ");
for(String token:tokens){
if(token.length()==0){//去空操作 " "
continue;
}else if(token.equals("+")||token.equals("-")){
while(!operatorStack.isEmpty()&&(operatorStack.peek()=='+'||operatorStack.peek()=='-'||operatorStack.peek()=='*'||operatorStack.peek()=='/')){
processOperator(numberStack,operatorStack);
}
operatorStack.push(token.charAt(0));//'('
}else if(token.equals("*")||token.equals("/")){
while(!operatorStack.isEmpty()&&(operatorStack.peek()=='*'||operatorStack.peek()=='/')){
processOperator(numberStack,operatorStack);
}
operatorStack.push(token.charAt(0));
}else if(token.equals("(")){
operatorStack.push(token.charAt(0));
}else if(token.equals(")")){
while(operatorStack.peek()!='('){ //直到’)‘ 遇到’(‘才停止运算
processOperator(numberStack,operatorStack);
}
operatorStack.pop();//去掉左括号
}else{
numberStack.push(Integer.valueOf(token));
}
}
while(!operatorStack.isEmpty()){
processOperator(numberStack,operatorStack);
}
return numberStack.pop();
}
private static void processOperator(ArrayStack<Integer> numberStack, ArrayStack<Character> operatorStack) {
int num1 = numberStack.pop();
int num2 = numberStack.pop();
char op = operatorStack.pop();//num2 op num1
if(op=='+'){
numberStack.push(num2+num1);
}else if(op=='-'){
numberStack.push(num2-num1);
}else if(op=='*'){
numberStack.push(num2*num1);
}else{
numberStack.push(num2/num1);
}
}
private static String insertBlanks(String s) {
StringBuilder sb = new StringBuilder();
for(int i = 0 ;i< s.length();i++){
char c = s.charAt(i);
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'){
sb.append(' ');
sb.append(c);
sb.append(' ');
}else{
sb.append(c);
}
}
return sb.toString();
}
}
7. 中缀表达式转后缀表达式(代码)
package p2.线性结构;
import java.util.ArrayList;
//中缀表达式转后缀表达式
public class InfixToSuffix {
public static void main(String[] args) {
String experssion = "(10+20/2*3)/2+8";
experssion = infixToSuffix(experssion);
System.out.println(experssion);
}
public static String infixToSuffix(String experssion) {
//操作符的栈
ArrayStack<String> opStack = new ArrayStack<>();
//后缀表达式的栈
ArrayList<String> suffixList = new ArrayList<>();
//格式化表达式
experssion = insertBlanks(experssion);
String [] tokens =experssion.split(" ");
for(String token:tokens){
if(token.length()==0){
continue;
}
if(isOperator(token)){
while(true){
if(opStack.isEmpty()||opStack.peek().equals("(")||priority(opStack.peek()) < priority(token)){
opStack.push(token);
break;
}
suffixList.add(opStack.pop());
}
}else if(token.equals("(")){
opStack.push(token);
}else if(token.equals(")")){
while(!opStack.peek().equals("(")){
suffixList.add(opStack.pop());
}
opStack.pop();
}else if(isNumber(token)){
suffixList.add(token);
}else{
throw new IllegalArgumentException("wrong char :"+experssion);
}
}
while(!opStack.isEmpty()){
suffixList.add(opStack.pop());
}
StringBuilder sb = new StringBuilder();
for(int i = 0 ;i < suffixList.size();i++){
sb.append(suffixList.get(i));
sb.append(' ');
}
return sb.toString();
}
private static int priority(String token) {
if(token.equals("+") || token.equals("-")){
return 0;
}
if(token.equals("*") || token.equals("/")){
return 1;
}
return -1;
}
private static boolean isNumber(String token) {
return token.matches("\\d+");
}
private static boolean isOperator(String token) {
return token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/");
}
private static String insertBlanks(String experssion) {
StringBuilder sb = new StringBuilder();
for(int i =0;i<experssion.length();i++){
char c = experssion.charAt(i);
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'){
sb.append(' ');
sb.append(c);
sb.append(' ');
}else {
sb.append(c);
}
}
return sb.toString();
}
}
8. 后缀表达式的计算器(代码)
package p2.线性结构;
public class SuffixCalculator {
public static void main(String[] args) {
String s1 = "(10+20/2*3)/2+8";
String s2 = InfixToSuffix.infixToSuffix(s1);
int result = evaluateSuffix(s2);
System.out.println(result);
}
private static int evaluateSuffix(String s2) {
ArrayStack<Integer> stack = new ArrayStack<>();
String[] tokens = s2.split(" ");
for(String token:tokens){
if(token.length()==0){
continue;
}
if(isNumber(token)){
stack.push(Integer.valueOf(token));
}else{
processAnOperator(stack,token);
}
}
return stack.pop();
}
private static void processAnOperator(ArrayStack<Integer> stack, String token) {
int num1 = stack.pop();
int num2 = stack.pop();
if(token.equals("+")){
stack.push(num2+num1);
}else if(token.equals("-")){
stack.push(num2-num1);
}else if(token.equals("*")){
stack.push(num2 * num1);
}else {
stack.push(num2 /num1);
}
}
private static boolean isNumber(String token) {
return token.matches("\\d+");
}
}
9. 十进制 转 十六进制(代码)
package p2.线性结构;
//十进制 转 十六进制
public class DecToHex {
public static void main(String[] args) {
int num = 654321;
ArrayStack<String> stack = new ArrayStack<>();
while (num != 0) {
int a = num % 16;
if (a < 10) {
stack.push(a + "");
} else {
//10-A 11-B 12-C 13-D 14-E 15-F
// 65 66 67 68 69 70
stack.push((char)(a + 55) + "");
}
num /= 16;
}
StringBuilder sb = new StringBuilder();
while (!stack.isEmpty()) {
sb.append(stack.pop());
}
System.out.println(sb.toString());
}
}
10. 十六进制 转 十进制(代码)
package p2.线性结构;
//十六进制 转 十进制
public class HexToDec {
public static void main(String[] args) {
String hex = "9FBF1";
ArrayStack<Character> stack = new ArrayStack<>();
for (int i = 0; i < hex.length(); i++) {
stack.push(hex.charAt(i));
}
int sum = 0;
int mi = 0;
while (!stack.isEmpty()) {
//9 F B F 1
char c = stack.pop(); // '1'
sum += getNumber(c) * Math.pow(16,mi);
mi++;
}
System.out.println(sum);
}
private static int getNumber(char c) {
if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F')) {
throw new IllegalArgumentException("wrong char!");
}
if (c >= '0' && c <= '9') {
return c - '0';
} else {
return c - 'A' + 10;
}
}
}
11. 判断回文(代码)
package p2.线性结构;
//判断回文
public class JudgingPalindrome {
public static void main(String[] args) {
solution01();
System.out.println(solution02());
}
private static boolean solution02() {
String text = "上海自来水来自海上";
int i = 0;
int j = text.length() - 1;
while (true) {
if (text.charAt(i) == text.charAt(j)) {
i++;
j--;
} else {
return false;
}
if (j <= i) {
return true;
}
}
}
private static void solution01() {
String text = "上海自来水来自海上"; //112233
ArrayStack<Character> stack = new ArrayStack<>();
for (int i = 0; i < text.length(); i++) {
if (text.length() % 2 == 1 && i == text.length() / 2) {
continue;
}
char c = text.charAt(i);
if (stack.isEmpty()) {
stack.push(c);
} else {
if (c != stack.peek()) {
stack.push(c);
} else {
stack.pop();
}
}
}
System.out.println(stack.isEmpty());
}
}
12. 括号匹配(代码)
package p2.线性结构;
import java.util.HashMap;
//括号匹配
public class MatchBracket {
public static void main(String[] args) {
solution01();//方法一:差值
solution02();//方法二:HashMap键值对
}
private static void solution02() {
String str = "{()[[()]]<>{}()<>}()";
HashMap<Character,Character> map = new HashMap<>();
map.put('[',']');
map.put('(',')');
map.put('<','>');
map.put('{','}');
ArrayStack<Character> stack = new ArrayStack<>();
for(int i = 0 ; i < str.length();i++){
char c = str.charAt(i);
if(stack.isEmpty()){
stack.push(c);
}else{
char top = stack.peek();
if(map.containsKey(top) && c==map.get(top)){
stack.pop();
}else{
stack.push(c);
}
}
}
System.out.println(stack.isEmpty());
}
private static void solution01() {
String str = "{()[[()]]<>{}()<>}()";
ArrayStack<Character> stack = new ArrayStack<>();
for(int i = 0 ; i < str.length();i++){
char c = str.charAt(i);
if(stack.isEmpty()){
stack.push(c);
}else{
char top = stack.peek();
if(c - top == 1 || c-top == 2){
stack.pop();
}else{
stack.push(c);
}
}
}
System.out.println(stack.isEmpty());
}
}
1.1.3双端栈
1.双端栈的定义
- 是指将一个线性表的两端当作栈底分别进行入栈和出栈操作
- 主要利用了“栈底位置不变,而栈顶位置动态变化”的特性。

2.ArrayDoubleEndStack类(代码)
- 双端栈是线性表的一种,更是栈的一个特殊分类
- 我们可以用动态数组和栈的思想来实现双端栈
- 由于栈操作过于特殊,并不能借助ArrayList和ArrayStack
package p2.线性结构;
import java.util.Arrays;
import java.util.Iterator;
//双端栈
public class ArrayDoubleEndStack<E> implements Iterable<E>{
//左端栈的栈顶
private int ltop;
//右端栈的栈顶
private int rtop;
//存储元素的容器
private E[] data;
//数组容器的默认容量
private static int DEFAULT_CAPACITY=10;
public ArrayDoubleEndStack() {
data = (E[]) new Object[DEFAULT_CAPACITY];
ltop=-1;
rtop=data.length;
}
public void pushLeft(E element){
if(ltop+1== rtop){
resize(data.length*2);
}
data[++ltop] = element;
}
private void resize(int newLen) {
E [] newData = (E[]) new Object[newLen];
//复制左端栈的元素
for(int i = 0; i <= ltop;i++){
newData[i] = data[i];
}
//复制右端栈的元素
int index = rtop;
for(int i = newLen - sizeRight();i< newLen;i++){
newData[i] = data[index++];
}
rtop = newLen -sizeRight();
data = newData;
}
public int sizeLeft(){//左端栈元素的个数
return ltop +1;
}
public int sizeRight(){//右端栈元素的个数
return data.length - rtop;
}
public void pushRight(E element){
data[--rtop] = element;
}
public E popLeft(){
if(isLeftEmpty()){
throw new IllegalArgumentException("left stack isn ull");
}
E ret = data[ltop--];
if(sizeLeft() + sizeRight() <= data.length /4 && data.length > DEFAULT_CAPACITY){
resize(data.length /2);
}
return ret;
}
public E popRight(){
if(isRightEmpty()){
throw new IllegalArgumentException("right stack isn ull");
}
E ret = data[rtop++];
if(sizeLeft() + sizeRight() <= data.length /4 && data.length > DEFAULT_CAPACITY){
resize(data.length /2);
}
return ret;
}
public boolean isLeftEmpty(){
return ltop == -1;
}
public boolean isRightEmpty(){
return rtop == data.length;
}
public E peekLeft(){
if(isLeftEmpty()){
throw new IllegalArgumentException("left stack isn ull");
}
return data[ltop];
}
public E peekRight(){
if(isRightEmpty()){
throw new IllegalArgumentException("right stack isn ull");
}
return data[rtop];
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append('[');
if(isLeftEmpty() && isRightEmpty()){
stringBuilder.append(']');
return stringBuilder.toString();
}
//先搞左边
for(int i = 0 ;i <= ltop;i++){
stringBuilder.append(data[i]);
if(i == ltop && isRightEmpty()){
stringBuilder.append(']');
return stringBuilder.toString();
}else{
stringBuilder.append(',');
}
}
//后搞右边
for(int i = rtop;i < data.length; i++){
stringBuilder.append(data[i]);
if(i == data.length -1){
stringBuilder.append(']');
}else{
stringBuilder.append(',');
}
}
return stringBuilder.toString();
}
@Override
public Iterator<E> iterator() {
return new ArrayDoubleEndStackIterator();
}
class ArrayDoubleEndStackIterator implements Iterator<E>{
private ArrayList<E> list;
private Iterator<E> it;
public ArrayDoubleEndStackIterator(){
list = new ArrayList<>();
for(int i = 0;i <= ltop;i++){
list.add(data[i]);
}
for(int i = rtop;i< data.length;i++){
list.add(data[i]);
}
it = list.iterator();
}
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public E next() {
return it.next();
}
}
}
3.TestArrayDoubleEndStack类(代码)
package p0.测试;
import p2.线性结构.ArrayDoubleEndStack;
public class TestArrayDoubleEndStack {
public static void main(String[] args) {
ArrayDoubleEndStack<Integer> stack01 = new ArrayDoubleEndStack<>();
System.out.println(stack01);
for(int i = 0 ;i < 10 ;i++){
stack01.pushLeft(i);
}
System.out.println(stack01);
ArrayDoubleEndStack<Integer> stack02 = new ArrayDoubleEndStack<>();
System.out.println(stack02);
for(int i = 0 ;i < 10 ;i++){
stack02.pushRight(i);
}
System.out.println(stack02);
ArrayDoubleEndStack<Integer> stack03 = new ArrayDoubleEndStack<>();
System.out.println(stack03);
for(int i = 0 ;i < 10 ;i++){
stack03.pushLeft(i);
stack03.pushRight(i);
}
System.out.println(stack03);
for(Integer num :stack03){
System.out.println(num);
}
}
}
1.1.4队列
1.队列的定义
- 队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表
- 我们把允许删除的一端称为队首(front),插入的一端称为队尾(rear)
- 不含任何数据元素的队列称为空队列
- 队列是一种先进先出(First In Last Out)的线性表,简称FIFO
- 队列本身是一个线性表,其数据元素具有线性关系,只不过它是一种特殊的线性表而已
- 队列的插入操作,叫作入队
- 队列的删除操作,叫作出队
2.队列接口的定义

3.队列接口的实现(代码)
package p1.接口;
public interface Queue<E> extends Iterable<E> {
public void offer(E element);
public E poll();
public E peek();
public boolean isEmpty();
public void clear();
public int size();
}
4.ArrayQueue队列的实现(代码)
package p2.线性结构;
import p1.接口.Queue;
import java.util.Iterator;
import java.util.Objects;
public class ArrayQueue<E> implements Queue<E> {
private ArrayList<E> list;
//以list为底层实现的队列
public ArrayQueue() {
list = new ArrayList<>();
}
@Override
public void offer(E element) {
list.add(list.size(),element);
}
@Override
public E poll() {
return list.remove(0);
}
@Override
public E peek() {
return list.get(0);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void clear() {
list.clear();
}
@Override
public int size() {
return list.size();
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public String toString() {
return list.toString();
}
@Override
public boolean equals(Object o) {
if(o == null){
return false;
}
if(this == o){
return true;
}
if(o instanceof ArrayQueue){
ArrayQueue other = (ArrayQueue) o;
return list.equals(other.list);
}
return false;
}
}
5.TestArrayQueue队列的测试(代码)
package p2.线性结构;
public class TestArrayQueue {
public static void main(String[] args) {
ArrayQueue<Integer> queue = new ArrayQueue<>();
for(int i = 0 ; i <10 ;i++){
queue.offer(i);
}
System.out.println(queue);
queue.poll();
queue.poll();
for(Integer q:queue){
System.out.print(q+" ");
}
}
}
6.文件夹遍历(代码)
package p2.线性结构;
import java.io.File;
public class DirectoryTraversal {
public static void main(String[] args) {
File dir = new File("D:\\Users\\PPDY\\IdeaProjects\\StructureProj");
ArrayQueue<File> queue = new ArrayQueue<>();
queue.offer(dir);
/**
* 只要队列不为空,则出队一个目录对象
* 将该目录对象展开 开始遍历 遇到文件则打印名称 遇到其他目录 则进队
*/
while(!queue.isEmpty()){
File file = queue.poll();
System.out.println("【"+file.getName()+"】");
File[] files = file.listFiles();
for(File f: files){
if(f.isFile()){
System.out.println(f.getName());
}else{
queue.offer(f);
}
}
}
}
}
7.栈实现队列(代码)
package p2.线性结构;
import p1.接口.Queue;
import java.util.Iterator;
public class StackToQueue {
public static void main(String[] args) {
QueueImplByStack<Integer> queueImplByStack = new QueueImplByStack<>();
for(int i = 1;i <=5 ;i++){
queueImplByStack.offer(i);
}
System.out.println(queueImplByStack);
System.out.println(queueImplByStack.poll());
System.out.println(queueImplByStack);
}
}
class QueueImplByStack<E> implements Queue<E>{
private ArrayStack<E> stackA;
private ArrayStack<E> stackB;
public QueueImplByStack(){
stackA = new ArrayStack<>();
stackB = new ArrayStack<>();
}
@Override
public void offer(E element) {
stackA.push(element);
}
@Override
public E poll() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
while(stackA.size() != 1){
stackB.push(stackA.pop());
}
E ret = stackA.pop();
while(!stackB.isEmpty()){
stackA.push(stackB.pop());
}
return ret;
}
@Override
public E peek() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
while(stackA.size() != 1){
stackB.push(stackA.pop());
}
E ret = stackA.peek();
while(!stackB.isEmpty()){
stackA.push(stackB.pop());
}
return ret;
}
@Override
public boolean isEmpty() {
return stackA.isEmpty();
}
@Override
public void clear() {
stackA.clear();
}
@Override
public int size() {
return stackA.size();
}
@Override
public Iterator<E> iterator() {
return stackA.iterator();
}
@Override
public String toString() {
return stackA.toString();
}
}
8.队列实现栈(代码)
package p2.线性结构;
import p1.接口.Stack;
import java.util.Iterator;
//队列实现栈
public class QueueToStack {
public static void main(String[] args) {
StackImplByQueue<Integer> stackImplByQueue = new StackImplByQueue<>();
System.out.println(stackImplByQueue);
for (int i = 1 ; i <= 5; i++){
stackImplByQueue.push(i);
}
System.out.println(stackImplByQueue);
System.out.println(stackImplByQueue.pop());
System.out.println(stackImplByQueue);
}
}
class StackImplByQueue<E> implements Stack<E>{
private ArrayQueue<E> queueA;
private ArrayQueue<E> queueB;
public StackImplByQueue() {
queueA = new ArrayQueue<>();
queueB = new ArrayQueue<>();
}
@Override
public int size() {
if(queueA.isEmpty() && queueB.isEmpty()){
return 0;
}else if(queueA.isEmpty()){
return queueB.size();
}else{
return queueA.size();
}
}
@Override
public boolean isEmpty() {
return queueA.isEmpty() && queueB.isEmpty();
}
@Override
public void push(E element) {
if(queueA.isEmpty() && queueB.isEmpty()){
queueA.offer(element);
}else if(!queueA.isEmpty() ){
queueA.offer(element);
}else {
queueB.offer(element);
}
}
@Override
public E pop() {
if(isEmpty()){
return null;
}
E ret = null;
if(!queueA.isEmpty()){
while(queueA.size()!=1){
queueB.offer(queueA.poll());
}
ret = queueA.poll();
}else {
while(queueB.size()!=1){
queueA.offer(queueB.poll());
}
ret = queueB.poll();
}
return ret;
}
@Override
public E peek() {
if(isEmpty()){
return null;
}
E ret = null;
if(!queueA.isEmpty()){
while(queueA.size()!=1){
queueB.offer(queueA.poll());
}
ret = queueA.peek();
queueB.offer(ret);
}else {
while(queueB.size()!=1){
queueA.offer(queueB.poll());
}
ret = queueB.peek();
queueA.offer(ret);
}
return ret;
}
@Override
public void clear() {
queueA.clear();
queueB.clear();
}
@Override
public Iterator<E> iterator() {
if(isEmpty()){
return queueA.iterator();
}else if(!queueA.isEmpty()){
return queueA.iterator();
}else {
return queueB.iterator();
}
}
@Override
public String toString() {
if(isEmpty()){
return "[]";
}else if(!queueA.isEmpty()){
return queueA.toString();
}else {
return queueB.toString();
}
}
}
1.1.5循环队列
- 队列入队时间复杂度是O(1),出队时间复杂度是O(n)
- 为了让时间复杂度都是O(1),用循环队列




package p2.线性结构;
import p1.接口.Queue;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Objects;
//循环队列
public class ArrayLoopQueue<E> implements Queue<E> {
private E [] data;
private int front;
private int rear;
private int size; //元素的个数(f < r r-f, r<f r+L-f)
private static int DEFAULT_CAPACITY = 10;
public ArrayLoopQueue() {
data = (E[]) new Object[DEFAULT_CAPACITY];
front = 0;
rear = 0;
size = 0;
}
@Override
public void offer(E element) {
//看看满了没
if((rear+1)%data.length == front){
resize(data.length * 2 -1);
}
data[rear] = element;
rear = (rear + 1) % data.length;
size++;
}
private void resize(int newLen) {
E [] newData = (E[]) new Object[newLen];
int index = 0;
for(int i = front ; i != rear ; i = (i+1) %data.length){
newData[index++] =data[i];
}
data = newData;
front=0;
rear =index;
}
@Override
public E poll() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
E ret = data[front];
front = (front+1)%data.length;
size--;
if(size <= (data.length-1) /4 && data.length - 1 > DEFAULT_CAPACITY){
resize(data.length / 2 + 1); }
return ret;
}
@Override
public E peek() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
return data[front];
}
@Override
public boolean isEmpty() {
return front == rear;
}
@Override
public void clear() {
data = (E[]) new Object[DEFAULT_CAPACITY];
size = 0;
front = 0;
rear = 0;
}
@Override
public int size() {
return size;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append('[');
if(isEmpty()){
stringBuilder.append(']');
return stringBuilder.toString();
}
for(int i =front ;i !=rear ;i = (i+1)%data.length){
stringBuilder.append(i);
if((i+1)%data.length ==rear){
stringBuilder.append(']');
}else {
stringBuilder.append(',');
stringBuilder.append(' ');
}
}
return stringBuilder.toString();
}
@Override
public boolean equals(Object o) {
if(o == null){
return false;
}
if(this == o){
return true;
}
if(o instanceof ArrayLoopQueue){
ArrayLoopQueue other = (ArrayLoopQueue) o;
if(this.size != other.size()){
return false;
}
int i = front;
int j = other.front;
while(i != rear){
if(!data[i].equals(other.data[j])){
return false;
}
i = (i +1)%data.length;
j=(j+1)%other.data.length;
}
}
return true;
}
@Override
public Iterator<E> iterator() {
return new ArrayLoopQueueIterator();
}
class ArrayLoopQueueIterator<E> implements Iterator<E> {
private int cur = front;
@Override
public boolean hasNext() {
return cur != rear;
}
@Override
public E next() {
E ret = (E) data[cur];
cur = (cur+1)% data.length;
return ret;
}
}
}
1.1.6双端队列
1.双端队列的定义

2.双端队列接口的实现(代码)
package p1.接口;
public interface Deque<E> extends Queue<E> {
public void addFirst(E element);
public void addLast(E element);
public E removeFirst();
public E removeLast();
public E getFirst();
public E getLast();
}
3.双端队列的实现(代码)

package p2.线性结构;
import p1.接口.Deque;
import p1.接口.Stack;
import java.util.Iterator;
public class ArrayDeque<E> implements Deque<E>, Stack<E> {
private E[] data;
private int front;
private int rear;
private int size;
private static int DEFAULT_CAPACITY = 10;
public ArrayDeque() {
data = (E[]) new Object[DEFAULT_CAPACITY+1];
front = 0;
rear = 0;
size = 0;
}
@Override
public void addFirst(E element) {
if((rear+1)%data.length==front){
resize(data.length*2-1);
}
front = (front -1 +data.length) %data.length;
data[front] = element;
size++;
}
private void resize(int newLen) {
E[] newData = (E[]) new Object[newLen];
int index = 0;
for(int i = front;i !=rear;i=(i+1)%data.length){
newData[index++] =data[i];
}
data = newData;
front=0;
rear =index;
}
@Override
public void addLast(E element) {
if((rear+1)%data.length==front){
resize(data.length*2-1);
}
data[rear] = element;
rear =(rear+1)%data.length;
size++;
}
@Override
public E removeFirst() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
E ret = data[front];
front = (front+1)%data.length;
size--;
if(size<=(data.length-1)/4&&data.length-1>DEFAULT_CAPACITY){
resize(data.length/2 +1);
}
return ret;
}
@Override
public E removeLast() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
rear = (rear-1+data.length)%data.length;
E ret = data[rear];
if(size<=(data.length-1)/4&&data.length-1>DEFAULT_CAPACITY){
resize(data.length/2 +1);
}
return ret;
}
@Override
public E getFirst() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
return data[front];
}
@Override
public E getLast() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
return data[(rear-1+data.length)%data.length];
}
@Override
public void offer(E element) {
addLast(element);
}
@Override
public E poll() {
return removeFirst();
}
@Override
public E peek() {
return getLast();
}
@Override
public boolean isEmpty() {
return size==0 && front==0;
}
@Override
public void push(E element) {
addLast(element);
}
@Override
public E pop() {
return removeLast();
}
@Override
public void clear() {
E[] data = (E[]) new Object[DEFAULT_CAPACITY];
front = 0;
rear = 0;
size =0;
}
@Override
public int size() {
return size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
if(isEmpty()){
sb.append(']');
return sb.toString();
}
for(int i = front;i !=rear;i=(i+1)%data.length){
sb.append(data[i]);
if((i+1)%data.length==rear){
sb.append(']');
}else{
sb.append(',');
sb.append(' ');
}
}
return sb.toString();
}
@Override
public Iterator<E> iterator() {
return new ArrayDequeIterator();
}
class ArrayDequeIterator implements Iterator<E>{
private int cur = front;
@Override
public boolean hasNext() {
return cur !=rear;
}
@Override
public E next() {
E ret = data[cur];
cur=(cur+1)%data.length;
return ret;
}
}
}
1.2链式存储(开辟一组随机的空间存储数据)
1.2.1链表
1.单向链表的实现(代码)
package p3.链式结构;
import p1.接口.List;
import java.util.Comparator;
import java.util.Iterator;
//单向链表
public class LinkedSinglyList<E> implements List<E> {
//定义结点对象
private class Node {
E data; //数据域
Node next; //指针域
public Node(){
this(null,null);
}
public Node(E data) {
this(data,null);
}
public Node(E data, Node next) {
this.data = data;
this.next = next;
}
@Override
public String toString() {
return data.toString();
}
}
private Node head; //头指针
private Node tail; //尾指针
private int size; //元素的个数
public LinkedSinglyList() {
head = null;
tail = null;
size = 0;
}
public LinkedSinglyList(E[] arr) {
if (arr == null || arr.length == 0) {
throw new IllegalArgumentException("arr is null");
}
for (int i = 0; i < arr.length; i++) {
add(arr[i]);
}
}
@Override
public void add(E element) {
add(size, element);
}
@Override
public void add(int index, E element) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("add index out of range");
}
Node n = new Node(element);
if (size == 0) {
head = n;
tail = n;
} else if (index == 0) {
n.next = head;
head = n;
} else if (index == size) {
tail.next = n;
tail = n;
} else {
Node p = head;
for (int i = 0; i < index - 1; i++) {
p = p.next;
}
n.next = p.next;
p.next = n;
}
size++;
}
@Override
public void remove(E element) {
int index = indexOf(element);
if (index != -1) {
remove(index);
}
}
@Override
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("remove index out of range");
}
E ret = null;
if (size == 1) {
ret = head.data;
head = null;
tail = null;
} else if (index == 0) {
Node n = head;
ret = n.data;
head = n.next;
n.next = null;
} else if (index == size - 1) {
Node p = head;
while (p.next != tail) {
p = p.next;
}
ret = tail.data;
p.next = null;
tail = p;
} else {
Node p = head;
for (int i = 0; i < index - 1; i++) {
p = p.next;
}
Node n = p.next;
ret = n.data;
p.next = n.next;
n.next = null;
}
size--;
return ret;
}
@Override
public E get(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("get index out of range");
}
if (index == 0) {
return head.data;
} else if (index == size - 1) {
return tail.data;
} else {
Node p = head;
for (int i = 0; i < index; i++) {
p = p.next;
}
return p.data;
}
}
@Override
public E set(int index, E element) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("get index out of range");
}
E ret = null;
if (index == 0) {
ret = head.data;
head.data = element;
} else if (index == size - 1) {
ret = tail.data;
tail.data = element;
} else {
Node p = head;
for (int i = 0; i < index; i++) {
p = p.next;
}
ret = p.data;
p.data = element;
}
return ret;
}
@Override
public int size() {
return size;
}
@Override
public int indexOf(E element) {
Node p = head;
int index = 0;
while (!p.data.equals(element)) {
p = p.next;
index++;
if (p == null) {
return -1;
}
}
return index;
}
@Override
public boolean contains(E element) {
return indexOf(element) != -1;
}
@Override
public boolean isEmpty() {
return size == 0 && head == null && tail == null;
}
@Override
public void clear() {
head = null;
tail = null;
size = 0;
}
@Override
public void sort(Comparator<E> c) {
if (c == null) {
throw new IllegalArgumentException("comparator can not be null");
}
//此处的插入排序O(n^3)
/*
for (int i = 1; i < size; i++) {
E e = get(i);
int j = 0;
for (j = i; j > 0 && c.compare(get(j - 1), e) > 0; j--) {
set(j, get(j - 1));
}
set(j, e);
}
*/
if (size == 0 || size == 1) {
return;
}
Node nodeA = head;
Node nodeB = nodeA.next;
while (true) {
while (true) {
if (c.compare(nodeA.data, nodeB.data) > 0) {
swap(nodeA, nodeB);
}
if (nodeB == tail) {
break;
}
nodeB = nodeB.next;
}
if (nodeA == tail) {
break;
}
nodeA = nodeA.next;
nodeB = nodeA.next;
}
}
private void swap(Node nodeA, Node nodeB) {
E temp = nodeA.data;
nodeA.data = nodeB.data;
nodeB.data = temp;
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
//0 <= fromIndex <= toIndex <= size - 1 [fromIndex,toIndex]
if (fromIndex < 0 || toIndex >= size || fromIndex > toIndex) {
throw new IllegalArgumentException("must 0 <= fromIndex <= toIndex <= size - 1");
}
LinkedSinglyList<E> list = new LinkedSinglyList<>();
/*
for (int i = fromIndex; i <= toIndex; i++) { //O(M)
list.add(get(i)); //O(N) * O(M) = O(NM) ~ O(N^2)
}
*/
Node nodeA = head;
for (int i = 0; i < fromIndex; i++) {
nodeA = nodeA.next;
}
Node nodeB = head;
for (int i = 0; i < toIndex; i++) {
nodeB = nodeB.next;
}
Node p = nodeA;
while (true) {
list.add(p.data);
if (p == nodeB) {
break;
}
p = p.next;
}
return list;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
if (isEmpty()) {
sb.append(']');
} else {
Node p = head;
while (true) {
sb.append(p.data);
if (p == tail) {
sb.append(']');
break;
}
sb.append(',');
sb.append(' ');
p = p.next;
}
}
return sb.toString();
}
@Override
public Iterator<E> iterator() {
return new LinkedSinglyListIterator();
}
class LinkedSinglyListIterator implements Iterator<E> {
private Node cur = head;
@Override
public boolean hasNext() {
return cur != null;
}
@Override
public E next() {
E ret = cur.data;
cur = cur.next;
return ret;
}
}
}
2.单向循环链表
package p3.链式结构;
import p1.接口.List;
import java.util.Comparator;
import java.util.Iterator;
public class LinkedSinglyCircularList<E> implements List<E> {
//定义结点对象
private class Node {
E data; //数据域
Node next; //指针域
public Node(){
this(null,null);
}
public Node(E data) {
this(data,null);
}
public Node(E data, Node next) {
this.data = data;
this.next = next;
}
@Override
public String toString() {
return data.toString();
}
}
private Node head; //头指针
private Node tail; //尾指针
private int size; //元素的个数
public LinkedSinglyCircularList() {
head = null;
tail = null;
size = 0;
}
public LinkedSinglyCircularList(E[] arr) {
if (arr == null || arr.length == 0) {
throw new IllegalArgumentException("arr is null");
}
for (int i = 0; i < arr.length; i++) {
add(arr[i]);
}
}
@Override
public void add(E element) {
add(size, element);
}
@Override
public void add(int index, E element) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("add index out of range");
}
Node n = new Node(element);
if (size == 0) {
head = n;
tail = n;
tail.next = head; //new code
} else if (index == 0) {
n.next = head;
head = n;
tail.next = head; //new code
} else if (index == size) {
n.next = tail.next; //new code
tail.next = n;
tail = n;
} else {
Node p = head;
for (int i = 0; i < index - 1; i++) {
p = p.next;
}
n.next = p.next;
p.next = n;
}
size++;
}
@Override
public void remove(E element) {
int index = indexOf(element);
if (index != -1) {
remove(index);
}
}
@Override
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("remove index out of range");
}
E ret = null;
if (size == 1) {
ret = head.data;
head = null;
tail = null;
} else if (index == 0) {
Node n = head;
ret = n.data;
head = n.next;
n.next = null;
tail.next = head; //new code
} else if (index == size - 1) {
Node p = head;
while (p.next != tail) {
p = p.next;
}
ret = tail.data;
p.next = tail.next; //change code
tail = p;
} else {
Node p = head;
for (int i = 0; i < index - 1; i++) {
p = p.next;
}
Node n = p.next;
ret = n.data;
p.next = n.next;
n.next = null;
}
size--;
return ret;
}
@Override
public E get(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("get index out of range");
}
if (index == 0) {
return head.data;
} else if (index == size - 1) {
return tail.data;
} else {
Node p = head;
for (int i = 0; i < index; i++) {
p = p.next;
}
return p.data;
}
}
@Override
public E set(int index, E element) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("get index out of range");
}
E ret = null;
if (index == 0) {
ret = head.data;
head.data = element;
} else if (index == size - 1) {
ret = tail.data;
tail.data = element;
} else {
Node p = head;
for (int i = 0; i < index; i++) {
p = p.next;
}
ret = p.data;
p.data = element;
}
return ret;
}
@Override
public int size() {
return size;
}
@Override
public int indexOf(E element) {
Node p = head;
int index = 0;
while (!p.data.equals(element)) {
p = p.next;
index++;
if (p == head) { //change code
return -1;
}
}
return index;
}
@Override
public boolean contains(E element) {
return indexOf(element) != -1;
}
@Override
public boolean isEmpty() {
return size == 0 && head == null && tail == null;
}
@Override
public void clear() {
head = null;
tail = null;
size = 0;
}
@Override
public void sort(Comparator<E> c) {
if (c == null) {
throw new IllegalArgumentException("comparator can not be null");
}
if (size == 0 || size == 1) {
return;
}
Node nodeA = head;
Node nodeB = nodeA.next;
while (true) {
while (true) {
if (c.compare(nodeA.data, nodeB.data) > 0) {
swap(nodeA, nodeB);
}
if (nodeB == tail) {
break;
}
nodeB = nodeB.next;
}
if (nodeA.next == tail) {
break;
}
nodeA = nodeA.next;
nodeB = nodeA.next;
}
}
private void swap(Node nodeA, Node nodeB) {
E temp = nodeA.data;
nodeA.data = nodeB.data;
nodeB.data = temp;
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
if (fromIndex < 0 || toIndex >= size || fromIndex > toIndex) {
throw new IllegalArgumentException("must 0 <= fromIndex <= toIndex <= size - 1");
}
LinkedSinglyList<E> list = new LinkedSinglyList<>();
Node nodeA = head;
for (int i = 0; i < fromIndex; i++) {
nodeA = nodeA.next;
}
Node nodeB = head;
for (int i = 0; i < toIndex; i++) {
nodeB = nodeB.next;
}
Node p = nodeA;
while (true) {
list.add(p.data);
if (p == nodeB) {
break;
}
p = p.next;
}
return list;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
if (isEmpty()) {
sb.append(']');
} else {
Node p = head;
while (true) {
sb.append(p.data);
if (p == tail) {
sb.append(']');
break;
}
sb.append(',');
sb.append(' ');
p = p.next;
}
}
return sb.toString();
}
@Override
public Iterator<E> iterator() {
return new LinkedSinglyCircularListIterator();
}
class LinkedSinglyCircularListIterator implements Iterator<E> {
private Node cur = head;
private boolean flag = true; //是否在第一圈
@Override
public boolean hasNext() {
if (isEmpty()) {
return false;
}
return flag;
}
@Override
public E next() {
E ret = cur.data;
cur = cur.next;
if (cur == head) {
flag = false;
}
return ret;
}
}
}
3.约瑟夫问题
public void josephusLoop(){
if(size <= 2){
return;
}
Node p = head;
while (size != 2){
p = p.next;
Node del = p.next;
if(del == head){
head = del.next;
}else if(del == tail){
tail = p;
}
p.next = del.next;
del.next = null;
p = p.next;
size--;
}
}
4.逢七过游戏
package p3.链式结构;
import java.util.ArrayList;
import java.util.Scanner;
//逢七过游戏
/*
输入玩家的个数
输入从哪个玩家开始
输入该玩家从哪个数字开始
输入一共玩几个数字
打印出每个玩家将要报出的所有数字
*/
public class SevenGame {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print(">>>请输入玩家的个数:");
int playerCount = input.nextInt();
System.out.print(">>>请输入从哪个玩家开始:");
int beginPlayer = input.nextInt();
System.out.print(">>>请输入从哪个数字开始:");
int beginNumber = input.nextInt();
System.out.print(">>>请输入数字的最大值:");
int maxNumber = input.nextInt();
//创建玩家的集合
LinkedSinglyCircularList<ArrayList<String>> list = new LinkedSinglyCircularList<>();
//分别创建玩家的对象
for (int i = 0; i < playerCount; i++) {
list.add(new ArrayList<>());
}
//开始的玩家的角标
int index = beginPlayer - 1;
//将数字 依次分给每一个玩家
for (int num = beginNumber; num <= maxNumber; num++) {
list.get(index++ % playerCount).add(getAnswer(num));
}
for (int i = 0; i < list.size(); i++) {
System.out.println("第" + (i + 1) + "位玩家:" + list.get(i));
}
}
private static String getAnswer(int num) {
if (num % 7 == 0 || (num + "").contains("7")) {
return "过";
}
return num + "";
}
}
本文详细介绍了Java中线性结构的实现,包括数组、线性表、栈、队列、双端栈、循环队列和双端队列。通过代码实例展示了动态数组的使用,以及如何利用数组实现栈、队列、双端栈和双端队列。此外,还探讨了线性表的ArrayList实现,以及栈和队列在实际问题中的应用,如中缀表达式转后缀表达式、括号匹配等。
554

被折叠的 条评论
为什么被折叠?



