
java和c++还是有不同之处的,写个数据结构熟悉一下java
链表
import java.util.Arrays;
public class arrlylist{
private int[] elem;
private int usedSize;
private static final int array_size=10;
public arrlylist(){
this.elem = new int[array_size];
}
public void display(){
System.out.println("Current list content:");
for (int i = 0;i < this.usedSize;++i)
{
System.out.println(this.elem[i]);
}
}
// Check if the list is full
public boolean isFull() {
return this.usedSize == this.elem.length;
}
// Add element at specified position
public void add(int pos, int data) {
// Check position validity
if (pos < 0 || pos > usedSize) {
System.out.println("Error: Invalid position!");
return;
}
// Check if need to expand
if (isFull()) {
this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
}
// Move elements after pos backward
for (int i = usedSize - 1; i >= pos; i--) {
this.elem[i + 1] = this.elem[i];
}
this.elem[pos] = data;
this.usedSize++;
}
// Add element at the end (overloaded method)
public void add(int data) {
add(this.usedSize, data);
}
public static void main(String[] args) {
System.out.println("hello arrlylist");
arrlylist list=new arrlylist();
list.add(1);
list.add(2);
list.add(3);
list.add(1, 99); // Insert 99 at index 1
list.display(); // Expected: [ 1, 99, 2, 3 ]
}
}
二叉树
import java.util.List;
import java.util.ArrayList;
class treenode{
int val;
treenode left;
treenode right;
public treenode(int val){
this.val=val;
}
}
public class tree{
private treenode root = null;
public void insert(int val)
{
if (root == null)
{
root = new treenode(val);
return;
}
treenode cur = root;
treenode parent = null;
while (cur != null)
{
parent = cur;
if (val < cur.val)
{
cur = cur.left;
}
else
{
cur = cur.right;
}
}
if (val < parent.val)
{
parent.left = new treenode(val);
}
else
{
parent.right = new treenode(val);
}
}
public List<treenode> preorder(treenode toor)
{
List<treenode> ret = new ArrayList<>();
if (root == null) return ret;
ret.add(toor);
List<treenode> left = preorder(toor.left);
ret.addAll(left);
List<treenode> right = preorder(toor.right);
ret.addAll(right);
return ret;
}
public static void main(String[] args) {
tree bst = new tree();
// 自动插入,不需要手动连线
int[] nodes = {50, 30, 70, 20, 40, 60, 80};
System.out.println("依次插入: 50, 30, 70, 20, 40, 60, 80");
for (int x : nodes) {
bst.insert(x);
}
}
}
哈希和set
哈希主要是一个key对应一个value,哈希值是key通过哈希函数得到,用哈希值可以在一个数组中作为下标找到value,如果哈希值算出来重复的话是哈希冲突,在同一个value里对应的值加一个,下标位挂一个链表,如果太长用红黑树解决。
set利用了哈希表中key是唯一值的特点,用来存储不重复的数据
七大排序

public class seven_sort{
public void unsort(int[] arr){
arr[6]=arr[0];
arr[0]=arr[1];
arr[1]=arr[2];
arr[2]=arr[3];
arr[3]=arr[4];
arr[4]=arr[5];
arr[5]=arr[6];
}
// 交换数组中两个元素的位置
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//O(n^2)三剑客
public void bubblesort(int[] arr){ // 冒泡排序 相邻比对,大的往后挪。每一趟能确定一个最大值到末尾。
int n=arr.length;
for(int i=0;i<n-1;i++){
for(int j=0;j<n-1-i;j++){
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
public void selectsort(int[] arr){//选择排序 定格位置,全场选最小
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) minIndex = j;
}
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
public void insertsort(int[] arr){//插入排序 待排元素插入到前面已经排好的有序序列中
for (int i = 1; i < arr.length; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && key < arr[j]) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
//改良排序
public void shellSort(int[] arr) {//希尔排序 先按增量(gap)分组排序,最后再来一次全体插排。
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < arr.length; i++) {
int key = arr[i], j = i;
while (j >= gap && arr[j - gap] > key) {
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = key;
}
}
}
public void heapSort(int[] arr) { //堆拿出最顶元素,然后最后的元素补到顶再重排成堆。利用二叉树的logn,减少计算量
// 1. 建堆
for (int i = arr.length / 2 - 1; i >= 0; i--) shiftDown(arr, i, arr.length);
// 2. 交换并调整
for (int i = arr.length - 1; i > 0; i--) {
swap(arr, 0, i);
shiftDown(arr, 0, i);
}
}
private void shiftDown(int[] arr, int i, int n) {
int temp = arr[i];
for (int k = 2 * i + 1; k < n; k = 2 * k + 1) {
if (k + 1 < n && arr[k] < arr[k + 1]) k++;
if (arr[k] > temp) { arr[i] = arr[k]; i = k; }
else break;
}
arr[i] = temp;
}
//分治排序法
//快速排序
public void quickSort(int[] arr, int left, int right) {//快速排序 选基准值(Pivot),小的放左,大的放右,递归进行。
if (left >= right) return;
int pivot = partition(arr, left, right);
quickSort(arr, left, pivot - 1);
quickSort(arr, pivot + 1, right);
}
private int partition(int[] arr, int left, int right) {
int pivot = arr[left];
while (left < right) {
while (left < right && arr[right] >= pivot) right--;
arr[left] = arr[right];
while (left < right && arr[left] <= pivot) left++;
arr[right] = arr[left];
}
arr[left] = pivot;
return left;
}
//归并排序
public void mergeSort(int[] arr, int l, int r) {//归并排序 先拆分到只剩一个数,再两两合并
if (l >= r) return;
if (l < r) {
int m = l + (r - l) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
private void merge(int[] arr, int l, int m, int r) {
int[] temp = new int[r - l + 1];
int i = l, j = m + 1, k = 0;
while (i <= m && j <= r) temp[k++] = (arr[i] <= arr[j]) ? arr[i++] : arr[j++];
while (i <= m) temp[k++] = arr[i++];
while (j <= r) temp[k++] = arr[j++];
System.arraycopy(temp, 0, arr, l, temp.length);
}
// 打印数组
public void printArray(int[] arr, String description) {
System.out.print(description + ": ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
System.out.println("=== 七大排序算法测试 ===");
seven_sort sorter = new seven_sort();
// 测试数据
int[] originalArr = {50, 30, 70, 20, 40, 60, 80};
// 1. 冒泡排序
int[] arr1 = originalArr.clone();
sorter.printArray(arr1, "冒泡排序前");
sorter.unsort(arr1);
sorter.printArray(arr1, "打乱后");
sorter.bubblesort(arr1);
sorter.printArray(arr1, "冒泡排序后");
System.out.println();
// 2. 选择排序
int[] arr2 = originalArr.clone();
sorter.printArray(arr2, "选择排序前");
sorter.unsort(arr2);
sorter.printArray(arr2, "打乱后");
sorter.selectsort(arr2);
sorter.printArray(arr2, "选择排序后");
System.out.println();
// 3. 插入排序
int[] arr3 = originalArr.clone();
sorter.printArray(arr3, "插入排序前");
sorter.unsort(arr3);
sorter.printArray(arr3, "打乱后");
sorter.insertsort(arr3);
sorter.printArray(arr3, "插入排序后");
System.out.println();
// 4. 希尔排序
int[] arr4 = originalArr.clone();
sorter.printArray(arr4, "希尔排序前");
sorter.unsort(arr4);
sorter.printArray(arr4, "打乱后");
sorter.shellSort(arr4);
sorter.printArray(arr4, "希尔排序后");
System.out.println();
// 5. 堆排序
int[] arr5 = originalArr.clone();
sorter.printArray(arr5, "堆排序前");
sorter.unsort(arr5);
sorter.printArray(arr5, "打乱后");
sorter.heapSort(arr5);
sorter.printArray(arr5, "堆排序后");
System.out.println();
// 6. 快速排序
int[] arr6 = originalArr.clone();
sorter.printArray(arr6, "快速排序前");
sorter.unsort(arr6);
sorter.printArray(arr6, "打乱后");
sorter.quickSort(arr6, 0, arr6.length - 1);
sorter.printArray(arr6, "快速排序后");
System.out.println();
// 7. 归并排序
int[] arr7 = originalArr.clone();
sorter.printArray(arr7, "归并排序前");
sorter.unsort(arr7);
sorter.printArray(arr7, "打乱后");
sorter.mergeSort(arr7, 0, arr7.length - 1);
sorter.printArray(arr7, "归并排序后");
System.out.println();
System.out.println("=== 测试完成 ===");
}
}
快速排序详解
1. 核心流程拆解
A. quickSort 方法 (分治递归)
这是一个典型的递归函数:
-
递归终止条件 :
left >= right。当子区间只有一个数或没有数时,不需要排序。 -
划分区间 :调用
partition找出基准值的准确位置pivot。 -
递归左右:对基准值左边的区间和右边的区间分别重复上述过程。
B. partition 方法 (挖坑填数)
这是快排最关键的逻辑,我们用一个例子演示:arr = [4, 7, 2, 5, 3]
-
选基准(挖坑) : 令
pivot = arr[left](即4)。此时,left位置(下标0)被视为一个**"坑"**。 -
右指针左移 (right--) : 从右往左找一个比 4 小 的数。发现
3比4小。-
填坑 :把
3填到left的坑位。 -
新坑 :此时
right位置(下标4)变成了新坑。
-
-
左指针右移 (left++) : 从左往右找一个比 4 大 的数。发现
7比4大。-
填坑 :把
7填到right的坑位。 -
新坑 :此时
left位置(下标1)变成了新坑。
-
-
循环终止 : 当
left == right时,说明所有数都比较过了,这个交汇点就是pivot该呆的位置。 -
回填基准 : 把最初的
4填入left这个最后的坑里。
归并排序解释
1. 核心流程:分、治、合
A. 递归拆分 (mergeSort 方法)
代码中的 int m = l + (r - l) / 2; 是为了防止 (l + r) / 2 可能导致的整数溢出。
-
分(Divide):将数组从中间一分为二。
-
治(Conquer):递归地对左半部分和右半部分进行归并排序。
-
合(Combine) :当子序列被拆到只有一个元素时(
l >= r),认为是有序的,开始向上合并。
B. 核心合并逻辑 (merge 方法)
这是归并排序的精华。它的任务是:将两个已经有序的子序列合并成一个新的、更大的有序序列。
-
开辟辅助空间 :
int[] temp = new int[r - l + 1];。归并排序不是原地排序,它需要额外的 O(n) 空间。 -
双指针赛跑:
-
i指向左半区起始,j指向右半区起始。 -
比较
arr[i]和arr[j],谁小就把谁塞进temp,然后对应的指针后移。
-
-
善后工作:
-
当其中一个半区跑完后,另一个半区可能还剩下一些数。
-
接下来的两个
while循环就是把剩下的"有序尾巴"直接搬进temp。
-
-
写回原数组 :使用
System.arraycopy将排好序的temp覆盖回原数组arr的对应区间[l, r]。
反射枚举lambda表达式
反射类可以调用私有的类的构造方法,但是开销更大,是一把双刃剑
反射无法读取枚举,枚举的单例是最安全的
1. 反射 (Reflection)
核心概念
反射允许程序在运行时 (Runtime) 取得任何类的内部信息(如成员变量、方法、构造器),并能直接操作任意对象的内部属性及方法。它是 Java 被称为"动态语言"的关键。
主要功能
-
在运行时判断任意一个对象所属的类。
-
在运行时构造任意一个类的对象。
-
在运行时获取/调用任意一个类所具有的成员变量和方法。
代码示例
Java
// 获取 Class 对象的三种方式
Class<?> c1 = Class.forName("com.example.User"); // 最常用
Class<?> c2 = User.class;
Class<?> c3 = userInstance.getClass();
// 动态创建对象并调用方法
Object obj = c1.getDeclaredConstructor().newInstance();
Method method = c1.getMethod("sayHello");
method.invoke(obj); // 执行方法
优缺点
-
优点: 极高的灵活性。它是所有框架(Spring, MyBatis 等)的底层基石(例如:Spring 的 IOC 容器就是通过反射读取配置并生成对象的)。
-
缺点: 性能开销大(比直接调用慢);破坏了封装性(可以强制访问 private 属性)。
2. 枚举 (Enum)
核心概念
枚举是一种特殊的类(Class),用于定义一组固定的常量。在 Java 中,枚举不仅仅是数字的别名,它是一个完整的对象,可以拥有字段、方法和构造器。
主要特点
-
类型安全: 编译器会检查类型,不能随意赋值。
-
单例模式: 枚举是实现单例模式最简单、最安全的方式(防止反射攻击)。
-
继承性: 所有枚举都自动继承
java.lang.Enum,因此不能再继承其他类,但可以实现接口。
代码示例
Java
public enum StatusCode {
SUCCESS(200, "操作成功"),
ERROR(500, "服务器错误");
private final int code;
private final String msg;
// 构造器默认是 private
StatusCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() { return code; }
}
// 使用
StatusCode status = StatusCode.SUCCESS;
if (status == StatusCode.SUCCESS) {
System.out.println(status.getCode()); // 输出 200
}
3. Lambda 表达式
核心概念
Lambda 是 Java 8 引入的新特性,用于简化函数式接口(只有一个抽象方法的接口)的实现。它让代码更简洁,并支持函数式编程风格。
核心语法
(参数列表) -> { 方法体 }
主要应用
-
简化匿名内部类: 尤其是
Runnable、Comparator等接口。 -
Stream API: 配合集合流式处理(过滤、映射、排序)。
代码示例
Java
// 1. 传统方式 vs Lambda
// 传统匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Running...");
}
}).start();
// Lambda 写法
new Thread(() -> System.out.println("Running...")).start();
// 2. 配合 Stream 处理集合
List<String> list = Arrays.asList("Java", "Python", "C++");
list.stream()
.filter(s -> s.startsWith("J")) // 筛选以 J 开头的
.map(String::toUpperCase) // 转大写
.forEach(System.out::println); // 输出
总结对比
| 特性 | 核心作用 | 关键词 | 一句话记忆 |
|---|---|---|---|
| 反射 | 动态性 | Class, Method, invoke |
"运行时扒开类的皮,直接操作内部。" |
| 枚举 | 规范性 | enum, values() |
"一组天然的、带属性的单例常量。" |
| Lambda | 简洁性 | ->, FunctionalInterface |
"把代码块像数据一样传递,消灭样板代码。" |
