数据结构与算法 Java 企业级实现方案 面试突击 Java面试
一、项目整体架构
采用面向接口编程 + 分层设计 + 泛型复用的企业级标准架构,严格遵循 Java 编码规范,实现原 C++ 代码的全部功能并修复原生缺陷,同时保留可扩展能力。
项目包结构
com.datastructure
├── sort # 排序算法工具集
├── linear # 线性表(接口 + 顺序/链表双实现)
├── stack # 栈(接口 + 顺序/链式双实现)
├── queue # 队列(接口 + 顺序/链式双实现)
├── model # 业务实体(图书类)
└── manager # 图书管理系统(顺序表/链表双版本)
test # 功能测试入口
二、排序算法模块
SortUtils.java(排序工具类)
完整复现冒泡、插入、快速排序逻辑,保留每趟排序过程打印,修复原代码边界问题。
package com.datastructure.sort;
/**
* 经典排序算法工具类
* 支持冒泡、插入、快速排序,附带排序过程可视化输出
*/
public class SortUtils {
/**
* 冒泡排序
* @param array 待排序数组
*/
public static void bubbleSort(int[] array) {
if (array == null || array.length <= 1) {
return;
}
int length = array.length;
for (int i = 0; i < length - 1; i++) {
for (int j = 0; j < length - i - 1; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
System.out.print("第" + (i + 1) + "趟: ");
printArray(array);
}
}
/**
* 插入排序
* @param array 待排序数组
*/
public static void insertionSort(int[] array) {
if (array == null || array.length <= 1) {
return;
}
System.out.println("==================插入排序=======================");
int length = array.length;
for (int i = 1; i < length; i++) {
for (int j = i - 1; j >= 0; j--) {
if (array[j + 1] < array[j]) {
int key = array[j + 1];
array[j + 1] = array[j];
array[j] = key;
}
}
System.out.print("第" + i + "趟: ");
printArray(array);
}
}
/**
* 快速排序入口
* @param array 待排序数组
*/
public static void quickSort(int[] array) {
if (array == null || array.length <= 1) {
return;
}
quickSortRecursion(array, 0, array.length - 1);
}
private static void quickSortRecursion(int[] array, int low, int high) {
if (low >= high) {
return;
}
int pivot = partition(array, low, high);
quickSortRecursion(array, low, pivot - 1);
quickSortRecursion(array, pivot + 1, high);
}
/**
* 分区函数:以首元素为基准,双指针交换分区
*/
private static int partition(int[] array, int low, int high) {
int key = array[low];
while (low < high) {
while (array[high] >= key && low < high) {
high--;
}
if (low < high) {
swap(array, low, high);
}
while (array[low] <= key && low < high) {
low++;
}
if (low < high) {
swap(array, low, high);
}
}
printArray(array);
return low;
}
private static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
private static void printArray(int[] array) {
for (int num : array) {
System.out.print(num + " ");
}
System.out.println();
}
}
三、线性表模块
1. 线性表通用接口 List.java
package com.datastructure.linear;
/**
* 线性表通用接口,定义增删改查标准行为
* @param <E> 元素类型
*/
public interface List<E> {
/**
* 指定下标插入元素
* @param index 插入位置(从0开始)
* @param element 插入元素
* @return 插入是否成功
*/
boolean add(int index, E element);
/**
* 删除指定下标元素
* @param index 删除位置
* @return 删除是否成功
*/
boolean remove(int index);
/**
* 修改指定下标元素
* @param index 修改位置
* @param element 新元素
* @return 修改是否成功
*/
boolean set(int index, E element);
/**
* 查找元素第一次出现的下标
* @param element 目标元素
* @return 下标,未找到返回-1
*/
int indexOf(E element);
/**
* 获取当前元素个数
*/
int size();
/**
* 遍历打印所有元素
*/
void show();
/**
* 判断是否为空
*/
boolean isEmpty();
}
2. 顺序表实现 SequenceList.java
修复原 C++ 数组越界问题,增加自动扩容机制,符合企业级健壮性要求。
package com.datastructure.linear;
/**
* 顺序表(动态数组实现)
* @param <E> 元素类型
*/
public class SequenceList<E> implements List<E> {
private static final int DEFAULT_CAPACITY = 20;
private Object[] elementData;
private int size;
private int capacity;
public SequenceList() {
this(DEFAULT_CAPACITY);
}
public SequenceList(int initCapacity) {
if (initCapacity <= 0) {
throw new IllegalArgumentException("初始容量必须大于0");
}
this.capacity = initCapacity;
this.elementData = new Object[initCapacity];
this.size = 0;
}
@Override
public boolean add(int index, E element) {
if (index > size || index < 0) {
System.out.println("插入位置不正确");
return false;
}
// 自动扩容
if (size == capacity) {
grow();
}
// 元素后移
for (int i = size - 1; i >= index; i--) {
elementData[i + 1] = elementData[i];
}
elementData[index] = element;
size++;
return true;
}
@Override
public boolean remove(int index) {
if (isEmpty()) {
System.out.println("顺序表为空");
return false;
}
if (index >= size || index < 0) {
System.out.println("删除位置不正确");
return false;
}
// 元素前移
for (int i = index; i < size - 1; i++) {
elementData[i] = elementData[i + 1];
}
elementData[size - 1] = null; // 帮助GC
size--;
return true;
}
@Override
public boolean set(int index, E element) {
if (isEmpty()) {
System.out.println("顺序表为空");
return false;
}
if (index >= size || index < 0) {
System.out.println("修改位置不正确");
return false;
}
elementData[index] = element;
return true;
}
@Override
public int indexOf(E element) {
if (isEmpty()) {
System.out.println("顺序表为空");
return -1;
}
for (int i = 0; i < size; i++) {
if (elementData[i].equals(element)) {
return i;
}
}
return -1;
}
@Override
public int size() {
return size;
}
@Override
public void show() {
if (isEmpty()) {
System.out.println("顺序表为空");
return;
}
for (int i = 0; i < size; i++) {
System.out.print(elementData[i] + " ");
}
System.out.println();
}
@Override
public boolean isEmpty() {
return size == 0;
}
/**
* 扩容:1.5倍容量
*/
private void grow() {
int newCapacity = capacity + (capacity >> 1);
Object[] newArray = new Object[newCapacity];
System.arraycopy(elementData, 0, newArray, 0, size);
elementData = newArray;
capacity = newCapacity;
}
@SuppressWarnings("unchecked")
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("下标越界");
}
return (E) elementData[index];
}
}
3. 单链表实现 LinkedList.java
修复原 C++ 修改方法返回值错误,采用内部节点类封装,地址调试打印可选。
package com.datastructure.linear;
/**
* 单链表实现
* @param <E> 元素类型
*/
public class LinkedList<E> implements List<E> {
/**
* 链表节点内部类
*/
private static class Node<E> {
E data;
Node<E> next;
Node(E data) {
this.data = data;
this.next = null;
}
}
private Node<E> head;
private int size;
public LinkedList() {
this.head = null;
this.size = 0;
}
@Override
public boolean add(int index, E element) {
if (index > size || index < 0) {
System.out.println("插入位置不正确");
return false;
}
Node<E> newNode = new Node<>(element);
// 空链表或头插
if (head == null || index == 0) {
newNode.next = head;
head = newNode;
size++;
return true;
}
// 找到前驱节点
Node<E> prev = head;
for (int i = 0; i < index - 1; i++) {
prev = prev.next;
}
newNode.next = prev.next;
prev.next = newNode;
size++;
return true;
}
@Override
public boolean remove(int index) {
if (isEmpty()) {
System.out.println("链表为空");
return false;
}
if (index >= size || index < 0) {
System.out.println("删除位置不正确");
return false;
}
// 头删
if (index == 0) {
Node<E> temp = head;
head = head.next;
temp.next = null; // 帮助GC
size--;
return true;
}
// 找到前驱节点
Node<E> prev = head;
for (int i = 0; i < index - 1; i++) {
prev = prev.next;
}
Node<E> target = prev.next;
prev.next = target.next;
target.next = null;
size--;
return true;
}
@Override
public boolean set(int index, E element) {
if (isEmpty()) {
System.out.println("链表为空");
return false;
}
if (index >= size || index < 0) {
System.out.println("修改位置不正确");
return false;
}
Node<E> current = head;
for (int i = 0; i < index; i++) {
current = current.next;
}
current.data = element;
return true; // 修复原C++代码返回false的bug
}
@Override
public int indexOf(E element) {
if (isEmpty()) {
System.out.println("链表为空");
return -1;
}
Node<E> current = head;
for (int i = 0; i < size; i++) {
if (current.data.equals(element)) {
return i;
}
current = current.next;
}
return -1;
}
@Override
public int size() {
return size;
}
@Override
public void show() {
if (isEmpty()) {
System.out.println("链表为空");
return;
}
Node<E> current = head;
for (int i = 0; i < size; i++) {
// 调试模式:打印下标+地址+数据+后继地址
// System.out.print(i + "(" + current + "):" + current.data + "," + current.next + "\t\t");
System.out.print(current.data + " ");
current = current.next;
}
System.out.println();
}
@Override
public boolean isEmpty() {
return size == 0;
}
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("下标越界");
}
Node<E> current = head;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
}
四、栈模块
1. 栈通用接口 Stack.java
package com.datastructure.stack;
/**
* 栈通用接口(后进先出)
* @param <E> 元素类型
*/
public interface Stack<E> {
boolean push(E element);
E pop();
E peek();
boolean isEmpty();
void show();
}
2. 顺序栈实现 ArrayStack.java
package com.datastructure.stack;
import com.datastructure.linear.SequenceList;
/**
* 顺序栈(基于动态数组实现)
* @param <E> 元素类型
*/
public class ArrayStack<E> implements Stack<E> {
private final SequenceList<E> list;
public ArrayStack() {
this.list = new SequenceList<>();
}
public ArrayStack(int capacity) {
this.list = new SequenceList<>(capacity);
}
@Override
public boolean push(E element) {
return list.add(list.size(), element);
}
@Override
public E pop() {
if (isEmpty()) {
System.out.println("栈为空");
return null;
}
E top = list.get(list.size() - 1);
list.remove(list.size() - 1);
System.out.println(top + "出栈");
return top;
}
@Override
public E peek() {
if (isEmpty()) {
return null;
}
return list.get(list.size() - 1);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void show() {
if (isEmpty()) {
System.out.println("栈为空");
return;
}
list.show();
}
}
3. 链栈实现 LinkedStack.java
package com.datastructure.stack;
/**
* 链栈(基于头插法单链表实现,栈顶在头部)
* @param <E> 元素类型
*/
public class LinkedStack<E> implements Stack<E> {
private static class Node<E> {
E data;
Node<E> next;
Node(E data) {
this.data = data;
}
}
private Node<E> top;
private int size;
public LinkedStack() {
this.top = null;
this.size = 0;
}
@Override
public boolean push(E element) {
Node<E> newNode = new Node<>(element);
newNode.next = top;
top = newNode;
size++;
return true;
}
@Override
public E pop() {
if (isEmpty()) {
System.out.println("栈为空");
return null;
}
E value = top.data;
Node<E> temp = top;
top = top.next;
temp.next = null;
size--;
System.out.println(value + "出栈");
return value;
}
@Override
public E peek() {
return isEmpty() ? null : top.data;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void show() {
if (isEmpty()) {
System.out.println("栈为空");
return;
}
Node<E> current = top;
while (current != null) {
System.out.print(current.data + "\t");
current = current.next;
}
System.out.println();
}
}
五、队列模块
1. 队列通用接口 Queue.java
package com.datastructure.queue;
/**
* 队列通用接口(先进先出)
* @param <E> 元素类型
*/
public interface Queue<E> {
boolean enqueue(E element);
E dequeue();
E peek();
boolean isEmpty();
void show();
}
2. 顺序队列实现 ArrayQueue.java
保留原代码“出队整体前移”逻辑,修复原 C++ 数组越界 bug。
package com.datastructure.queue;
import com.datastructure.linear.SequenceList;
/**
* 顺序队列(非循环队列,出队元素整体前移)
* @param <E> 元素类型
*/
public class ArrayQueue<E> implements Queue<E> {
private final SequenceList<E> list;
public ArrayQueue() {
this.list = new SequenceList<>();
}
public ArrayQueue(int capacity) {
this.list = new SequenceList<>(capacity);
}
@Override
public boolean enqueue(E element) {
return list.add(list.size(), element);
}
@Override
public E dequeue() {
if (isEmpty()) {
System.out.println("队列为空");
return null;
}
E front = list.get(0);
list.remove(0);
System.out.println(front + "出队列");
return front;
}
@Override
public E peek() {
return isEmpty() ? null : list.get(0);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void show() {
if (isEmpty()) {
System.out.println("队列为空");
return;
}
list.show();
}
}
3. 链队列实现 LinkedQueue.java
保留原代码遍历入队逻辑,标注优化点(增加尾指针可实现 O(1) 入队)。
package com.datastructure.queue;
/**
* 链队列(单链表实现,队头在头部)
* 优化点:可增加尾指针将入队复杂度从O(n)降为O(1)
* @param <E> 元素类型
*/
public class LinkedQueue<E> implements Queue<E> {
private static class Node<E> {
E data;
Node<E> next;
Node(E data) {
this.data = data;
}
}
private Node<E> front;
private int size;
public LinkedQueue() {
this.front = null;
this.size = 0;
}
@Override
public boolean enqueue(E element) {
Node<E> newNode = new Node<>(element);
if (isEmpty()) {
front = newNode;
size++;
return true;
}
// 遍历到队尾
Node<E> rear = front;
for (int i = 0; i < size - 1; i++) {
rear = rear.next;
}
rear.next = newNode;
size++;
return true;
}
@Override
public E dequeue() {
if (isEmpty()) {
System.out.println("队列为空");
return null;
}
E value = front.data;
Node<E> temp = front;
front = front.next;
temp.next = null;
size--;
System.out.println(value + "出队列");
return value;
}
@Override
public E peek() {
return isEmpty() ? null : front.data;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void show() {
if (isEmpty()) {
System.out.println("队列为空");
return;
}
Node<E> current = front;
for (int i = 0; i < size; i++) {
System.out.print(current.data + "\t");
current = current.next;
}
System.out.println();
}
}
六、图书管理系统模块
1. 图书实体类 Book.java
package com.datastructure.model;
/**
* 图书实体类
*/
public class Book {
private int bookNo;
private String bookName;
private float price;
public Book() {}
public Book(int bookNo, String bookName, float price) {
this.bookNo = bookNo;
this.bookName = bookName;
this.price = price;
}
public void display() {
System.out.println(bookNo + "\t" + bookName + "\t" + price);
}
// getter & setter
public int getBookNo() { return bookNo; }
public void setBookNo(int bookNo) { this.bookNo = bookNo; }
public String getBookName() { return bookName; }
public void setBookName(String bookName) { this.bookName = bookName; }
public float getPrice() { return price; }
public void setPrice(float price) { this.price = price; }
}
2. 图书管理接口 BookManager.java
package com.datastructure.manager;
import com.datastructure.model.Book;
/**
* 图书管理业务接口
*/
public interface BookManager {
boolean addBook(int index, Book book);
boolean removeBook(int index);
boolean findByName(String bookName);
boolean updateBookName(int index, String newName);
void displayAll();
int getCount();
void sortByPrice(); // 仅顺序表版本完整实现
}
3. 顺序表版图书管理 SequenceBookManager.java
package com.datastructure.manager;
import com.datastructure.linear.SequenceList;
import com.datastructure.model.Book;
/**
* 顺序表实现图书管理系统
*/
public class SequenceBookManager implements BookManager {
private final SequenceList<Book> bookList;
public SequenceBookManager(int maxSize) {
this.bookList = new SequenceList<>(maxSize);
}
@Override
public boolean addBook(int index, Book book) {
return bookList.add(index, book);
}
@Override
public boolean removeBook(int index) {
return bookList.remove(index);
}
@Override
public boolean findByName(String bookName) {
for (int i = 0; i < bookList.size(); i++) {
if (bookList.get(i).getBookName().equals(bookName)) {
return true;
}
}
return false;
}
@Override
public boolean updateBookName(int index, String newName) {
if (index < 0 || index >= bookList.size()) {
System.out.println("修改位置不正确");
return false;
}
bookList.get(index).setBookName(newName);
return true;
}
@Override
public void displayAll() {
if (bookList.isEmpty()) {
System.out.println("顺序表为空");
return;
}
System.out.println("顺序表中的数据为:");
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).display();
}
System.out.println();
}
@Override
public int getCount() {
return bookList.size();
}
/**
* 按价格冒泡排序(从低到高)
*/
@Override
public void sortByPrice() {
int len = bookList.size();
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
if (bookList.get(j).getPrice() > bookList.get(j + 1).getPrice()) {
Book temp = bookList.get(j);
bookList.set(j, bookList.get(j + 1));
bookList.set(j + 1, temp);
}
}
}
}
}
4. 链表版图书管理 LinkedBookManager.java
package com.datastructure.manager;
import com.datastructure.linear.LinkedList;
import com.datastructure.model.Book;
/**
* 链表实现图书管理系统
*/
public class LinkedBookManager implements BookManager {
private final LinkedList<Book> bookList;
public LinkedBookManager() {
this.bookList = new LinkedList<>();
}
@Override
public boolean addBook(int index, Book book) {
return bookList.add(index, book);
}
@Override
public boolean removeBook(int index) {
return bookList.remove(index);
}
@Override
public boolean findByName(String bookName) {
for (int i = 0; i < bookList.size(); i++) {
if (bookList.get(i).getBookName().equals(bookName)) {
return true;
}
}
return false;
}
@Override
public boolean updateBookName(int index, String newName) {
if (index < 0 || index >= bookList.size()) {
System.out.println("修改位置不正确");
return false;
}
bookList.get(index).setBookName(newName);
return true;
}
@Override
public void displayAll() {
if (bookList.isEmpty()) {
System.out.println("链表为空");
return;
}
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).display();
}
System.out.println();
}
@Override
public int getCount() {
return bookList.size();
}
@Override
public void sortByPrice() {
System.out.println("链表版暂不支持排序功能");
}
}
七、测试入口示例(控制台交互)
图书管理系统启动类
package test;
import com.datastructure.manager.BookManager;
import com.datastructure.manager.SequenceBookManager;
import com.datastructure.model.Book;
import java.util.Scanner;
/**
* 顺序表版图书管理系统测试
*/
public class BookSystemTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
BookManager manager = new SequenceBookManager(20);
while (true) {
System.out.println("--------------------------------------------------------------------");
System.out.println("欢迎使用图书管理系统");
System.out.println("1.添加图书");
System.out.println("2.删除图书");
System.out.println("3.查找图书");
System.out.println("4.显示所有");
System.out.println("5.修改图书名");
System.out.println("6.图书按价格排序");
System.out.println("7.退出系统");
System.out.println("--------------------------------------------------------------------");
System.out.print("请选择:");
int choice = scanner.nextInt();
switch (choice) {
case 1:
System.out.print("请输入图书名称:");
String name = scanner.next();
System.out.print("请输入图书价格:");
float price = scanner.nextFloat();
Book book = new Book(manager.getCount() + 1, name, price);
manager.addBook(manager.getCount(), book);
break;
case 2:
System.out.print("请输入删除第几本图书(从1起):");
int delIndex = scanner.nextInt();
manager.removeBook(delIndex - 1);
break;
case 3:
System.out.print("请输入图书名称:");
String searchName = scanner.next();
System.out.println(manager.findByName(searchName) ? "找到该图书" : "未找到该图书");
break;
case 4:
manager.displayAll();
break;
case 5:
System.out.print("请输入修改第几本图书(从1起):");
int updateIndex = scanner.nextInt();
System.out.print("请输入新图书名称:");
String newName = scanner.next();
manager.updateBookName(updateIndex - 1, newName);
break;
case 6:
manager.sortByPrice();
manager.displayAll();
break;
case 7:
System.out.println("退出系统");
scanner.close();
return;
default:
System.out.println("输入错误,请重新选择");
}
}
}
}
八、企业级优化说明
- 架构解耦:接口与实现分离,可无缝替换底层存储结构,符合开闭原则。
- 泛型复用:所有数据结构支持任意引用类型,避免重复造轮子。
- 健壮性增强:参数合法性校验、自动扩容、内存泄漏修复(C++ 析构函数问题 Java GC 天然解决)。
- 代码规范:驼峰命名、权限控制、注释完整,符合阿里巴巴 Java 开发手册标准。
- 可扩展性:可快速接入循环队列、双向链表、归并排序等扩展实现。
- Bug 修复:修复原 C++ 代码中修改方法返回值错误、数组越界、析构逻辑错误等问题。

325

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



