【基本数据结构】:字符串,数组,队列,栈,哈希表,链表,二叉树,图,堆,
【常用方法】Integer.MAX_VALUE;
1970年1月1日式星期四
一.字符串
创建字符串
- 直接赋值: String str = "Hello World";
- 使用 new 关键字: String str = new String("Hello World");
常用方法
- length() :返回字符串的长度。例如 "Hello".length() 返回5。
- charAt(int index) :返回指定索引处的字符。如 "Hello".charAt(1) 返回'e'。
- substring(int beginIndex) 和 substring(int beginIndex, int endIndex) :截取字符串。 "Hello".substring(2) 返回"llo", "Hello".substring(1, 3) 返回"el"。
- equals(Object anObject) :比较两个字符串内容是否相等。 "Hello".equals("hello") 返回false。
- equalsIgnoreCase(String anotherString) :忽略大小写比较字符串内容是否相等。 "Hello".equalsIgnoreCase("hello") 返回true。
- compareTo(String anotherString) :按字典顺序比较两个字符串。返回值为负表示当前字符串小于参数字符串,为0表示相等,为正表示大于。
- contains(CharSequence s) :判断字符串是否包含指定的字符序列。 "Hello".contains("ll") 返回true。
- indexOf(int ch) 和 indexOf(String str) :返回指定字符或子串首次出现的索引,不存在则返回-1。 "Hello".indexOf("l") 返回2。
- lastIndexOf(int ch) 和 lastIndexOf(String str) :返回指定字符或子串最后一次出现的索引,不存在返回-1。 "Hello".lastIndexOf("l") 返回3。
- replace(char oldChar, char newChar) 和 replace(CharSequence target, CharSequence replacement) :替换字符或字符序列。 "Hello".replace("l", "x") 返回"Hexxo"。
- split(String regex) :根据指定的正则表达式拆分字符串,返回字符串数组。 "Hello World".split(" ") 返回 ["Hello", "World"] 。
- trim() :去除字符串开头和结尾的空格。 " Hello ".trim() 返回"Hello"。
- toUpperCase() 和 toLowerCase() :将字符串转换为大写或小写形式。 "Hello".toUpperCase() 返回"HELLO", "Hello".toLowerCase() 返回"hello"。
public class Test{
public static void main(String[] args) {
// 创建字符串
String str = "Hello World";
// length()方法:获取字符串长度
int length = str.length();
// charAt()方法:获取指定索引字符
char ch = str.charAt(3);
// substring()方法:截取子串
String subStr = str.substring(1, 5);
// equals()方法:比较字符串内容是否相等
boolean isEqual = str.equals("Hello World");
// toUpperCase()方法:转换为大写
String upperCaseStr = str.toUpperCase();
// split()方法:按空格拆分字符串
String[] splitArr = str.split(" ");
// replace()方法:替换子串
String replacedStr = str.replace("World", "Java");
// 使用StringBuilder反转字符串
StringBuilder sb = new StringBuilder(str);
sb.reverse();
}
}
二.数组
public static void main(String[] args) {
// 创建一个整型数组
int[] arr = {1, 2, 3, 4, 5};
// 访问数组元素:通过索引访问数组中的元素
int element = arr[2];
System.out.println("数组索引为2的元素是: " + element);
// 数组长度:使用 length 属性获取数组的长度
int length = arr.length;
System.out.println("数组的长度是: " + length);
// 遍历数组:使用 for 循环遍历数组
System.out.print("数组元素: ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
// 遍历数组:使用增强型 for 循环(for-each)遍历数组
System.out.print("使用 for-each 遍历数组元素: ");
for (int num : arr) {
System.out.print(num + " ");
}
System.out.println();
// 复制数组:使用 System.arraycopy 方法复制数组
int[] newArr = new int[arr.length];
System.arraycopy(arr, 0, newArr, 0, arr.length);
System.out.println("复制后的数组元素: ");
for (int num : newArr) {
System.out.print(num + " ");
}
System.out.println();
// 数组排序:使用 java.util.Arrays.sort 方法对数组排序
int[] sortArr = {5, 3, 1, 4, 2};
java.util.Arrays.sort(sortArr);
System.out.print("排序后的数组元素: ");
for (int num : sortArr) {
System.out.print(num + " ");
}
System.out.println();
// 查找元素:使用 java.util.Arrays.binarySearch 方法在已排序数组中查找元素
int searchIndex = java.util.Arrays.binarySearch(sortArr, 3);
System.out.println("在排序数组中查找元素3的索引是: " + searchIndex);
}
三.队列
queue.toArray(new String[size])
import java.util.LinkedList;
import java.util.Queue;
public class Test{
public static void main(String[] args) {
// 创建一个队列,使用 LinkedList 实现
Queue<Integer> queue = new LinkedList<>();
// 添加元素:offer 方法向队列尾部添加元素,成功返回 true,失败返回 false
boolean offerResult = queue.offer(10);
System.out.println("使用 offer 添加元素 10,结果: " + offerResult);
// 添加元素:add 方法向队列尾部添加元素,成功返回 true,失败抛出异常
try {
boolean addResult = queue.add(20);
System.out.println("使用 add 添加元素 20,结果: " + addResult);
} catch (Exception e) {
System.out.println("使用 add 添加元素时抛出异常: " + e.getMessage());
}
// 查看队头元素:peek 方法获取队头元素,队列为空时返回 null
Integer peekElement = queue.peek();
System.out.println("使用 peek 获取队头元素: " + peekElement);
// 查看队头元素:element 方法获取队头元素,队列为空时抛出异常
try {
Integer element = queue.element();
System.out.println("使用 element 获取队头元素: " + element);
} catch (Exception e) {
System.out.println("使用 element 获取元素时抛出异常: " + e.getMessage());
}
// 移除队头元素:poll 方法移除并返回队头元素,队列为空时返回 null
Integer pollElement = queue.poll();
System.out.println("使用 poll 移除并返回队头元素: " + pollElement);
// 移除队头元素:remove 方法移除并返回队头元素,队列为空时抛出异常
try {
Integer removeElement = queue.remove();
System.out.println("使用 remove 移除并返回队头元素: " + removeElement);
} catch (Exception e) {
System.out.println("使用 remove 移除元素时抛出异常: " + e.getMessage());
}
// 判断队列是否为空:isEmpty 方法判断队列是否为空
boolean isEmpty = queue.isEmpty();
System.out.println("队列是否为空: " + isEmpty);
// 获取队列大小:size 方法获取队列中元素的数量
int size = queue.size();
System.out.println("队列的大小是: " + size);
}
}
四.栈
import java.util.Stack;
public class StackMethodExample {
public static void main(String[] args) {
// 创建一个栈
Stack<Integer> stack = new Stack<>();
// 压栈操作:push 方法将元素压入栈顶
stack.push(10);
stack.push(20);
stack.push(30);
System.out.println("压入元素 10, 20, 30 后的栈: " + stack);
// 查看栈顶元素:peek 方法返回栈顶元素,但不删除它
int peekElement = stack.peek();
System.out.println("使用 peek 查看栈顶元素: " + peekElement);
// 出栈操作:pop 方法移除并返回栈顶元素
int popElement = stack.pop();
System.out.println("使用 pop 移除并返回栈顶元素: " + popElement + ",此时栈: " + stack);
// 查找元素在栈中的位置:search 方法返回元素在栈中的位置,从栈顶开始计数,不存在则返回 -1
int position = stack.search(10);
System.out.println("元素 10 在栈中的位置(从栈顶开始计数): " + position);
// 判断栈是否为空:empty 方法判断栈是否为空
boolean isEmpty = stack.empty();
System.out.println("栈是否为空: " + isEmpty);
// 获取栈的大小:size 方法获取栈中元素的数量
int size = stack.size();
System.out.println("栈的大小是: " + size);
}
}
五.哈希表
import java.util.HashMap;
import java.util.Map;
public class HashMapMethodExample {
public static void main(String[] args) {
// 创建一个 HashMap
Map<String, Integer> hashMap = new HashMap<>();
// put 方法:将键值对存入 Map 中,如果键已存在,会覆盖原来的值
hashMap.put("apple", 10);
hashMap.put("banana", 20);
hashMap.put("cherry", 30);
System.out.println("存入键值对后的 HashMap: " + hashMap);
// get 方法:根据键获取对应的值,如果键不存在,返回 null
int value = hashMap.get("banana");
System.out.println("键 banana 对应的值: " + value);
// containsKey 方法:判断 Map 是否包含指定的键
boolean hasKey = hashMap.containsKey("cherry");
System.out.println("HashMap 是否包含键 cherry: " + hasKey);
// containsValue 方法:判断 Map 是否包含指定的值
boolean hasValue = hashMap.containsValue(20);
System.out.println("HashMap 是否包含值 20: " + hasValue);
// size 方法:获取 Map 中键值对的数量
int size = hashMap.size();
System.out.println("HashMap 中键值对的数量: " + size);
// remove 方法:根据键移除对应的键值对,返回被移除的值,如果键不存在,返回 null
int removedValue = hashMap.remove("apple");
System.out.println("移除键 apple 对应的值: " + removedValue + ",此时 HashMap: " + hashMap);
// keySet 方法:返回一个包含所有键的 Set 集合
System.out.println("HashMap 中的所有键: " + hashMap.keySet());
// values 方法:返回一个包含所有值的 Collection 集合
System.out.println("HashMap 中的所有值: " + hashMap.values());
// entrySet 方法:返回一个包含所有键值对的 Set 集合,每个元素是一个 Map.Entry 对象
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
System.out.println("键: " + entry.getKey() + ",值: " + entry.getValue());
}
// clear 方法:移除 Map 中的所有键值对
hashMap.clear();
System.out.println("清空后的 HashMap: " + hashMap);
}
}
六.链表
【基本方法】
list.toArray(new String[list.size()])
import java.util.LinkedList;
public class LinkedListMethodExample {
public static void main(String[] args) {
// 创建一个 LinkedList
LinkedList<String> linkedList = new LinkedList<>();
// add(E e) 方法:在链表末尾添加元素
linkedList.add("apple");
linkedList.add("banana");
linkedList.add("cherry");
System.out.println("添加元素后的链表: " + linkedList);
// add(int index, E element) 方法:在指定位置插入元素
linkedList.add(1, "orange");
System.out.println("在索引 1 处插入元素后的链表: " + linkedList);
// get(int index) 方法:获取指定位置的元素
String element = linkedList.get(2);
System.out.println("索引 2 处的元素: " + element);
// set(int index, E element) 方法:修改指定位置的元素
linkedList.set(0, "pear");
System.out.println("修改索引 0 处元素后的链表: " + linkedList);
// remove(int index) 方法:移除指定位置的元素
String removedElement = linkedList.remove(1);
System.out.println("移除索引 1 处元素: " + removedElement + ",此时链表: " + linkedList);
// remove(Object o) 方法:移除指定元素的第一个匹配项
boolean removeResult = linkedList.remove("cherry");
System.out.println("移除元素 cherry,结果: " + removeResult + ",此时链表: " + linkedList);
// size() 方法:获取链表的大小(元素个数)
int size = linkedList.size();
System.out.println("链表的大小: " + size);
// isEmpty() 方法:判断链表是否为空
boolean isEmpty = linkedList.isEmpty();
System.out.println("链表是否为空: " + isEmpty);
// contains(Object o) 方法:判断链表是否包含指定元素
boolean contains = linkedList.contains("pear");
System.out.println("链表是否包含元素 pear: " + contains);
// clear() 方法:清空链表
linkedList.clear();
System.out.println("清空后的链表: " + linkedList);
}
}
【手写链表】代码首先定义了链表节点类 ListNode ,然后实现了一个 MyLinkedList 类来管理链表,包括链表的初始化、获取节点值、在头部、尾部和指定索引处添加节点以及删除指定索引处的节点等方法。最后通过 Main 类中的 main 方法进行了简单的测试。
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
this.next = null;
}
}
class MyLinkedList {
private ListNode head;
// 初始化链表
public MyLinkedList() {
head = null;
}
// 获取指定索引处的节点值
public int get(int index) {
ListNode current = head;
int count = 0;
while (current != null && count < index) {
current = current.next;
count++;
}
return current != null? current.val : -1;
}
// 在链表头部添加节点
public void addAtHead(int val) {
ListNode newNode = new ListNode(val);
newNode.next = head;
head = newNode;
}
// 在链表尾部添加节点
public void addAtTail(int val) {
ListNode newNode = new ListNode(val);
if (head == null) {
head = newNode;
} else {
ListNode current = head;
while (current.next != null) {
current = current.next;
}
current.next = newNode;
}
}
// 在指定索引处添加节点
public void addAtIndex(int index, int val) {
if (index == 0) {
addAtHead(val);
return;
}
ListNode current = head;
int count = 0;
while (current != null && count < index - 1) {
current = current.next;
count++;
}
if (current != null) {
ListNode newNode = new ListNode(val);
newNode.next = current.next;
current.next = newNode;
}
}
// 删除指定索引处的节点
public void deleteAtIndex(int index) {
if (head == null) {
return;
}
if (index == 0) {
head = head.next;
return;
}
ListNode current = head;
int count = 0;
while (current != null && count < index - 1) {
current = current.next;
count++;
}
if (current != null && current.next != null) {
current.next = current.next.next;
}
}
}
public class Main {
public static void main(String[] args) {
MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1, 2);
System.out.println(linkedList.get(1));
linkedList.deleteAtIndex(1);
System.out.println(linkedList.get(1));
}
}
七.二叉树
在Java中,二叉树是一种重要的数据结构,下面以简单的二叉树节点类和包含一些常用方法的二叉树类为例进行展示,包括二叉树节点的定义、二叉树的构建以及常见的遍历方法(前序遍历、中序遍历、后序遍历、层序遍历)等。
上述代码首先定义了 TreeNode 类表示二叉树的节点,然后 BinaryTree 类包含了二叉树的一些常用操作方法,如各种遍历方式和简单的插入方法。最后通过 Main 类的 main 方法进行了测试。
// 定义二叉树节点类
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
this.left = null;
this.right = null;
}
}
// 定义二叉树类
class BinaryTree {
private TreeNode root;
// 构造函数,初始化二叉树
public BinaryTree() {
root = null;
}
// 前序遍历:根节点 -> 左子树 -> 右子树
public void preorderTraversal() {
preorderTraversal(root);
}
private void preorderTraversal(TreeNode node) {
if (node!= null) {
System.out.print(node.val + " ");
preorderTraversal(node.left);
preorderTraversal(node.right);
}
}
// 中序遍历:左子树 -> 根节点 -> 右子树
public void inorderTraversal() {
inorderTraversal(root);
}
private void inorderTraversal(TreeNode node) {
if (node!= null) {
inorderTraversal(node.left);
System.out.print(node.val + " ");
inorderTraversal(node.right);
}
}
// 后序遍历:左子树 -> 右子树 -> 根节点
public void postorderTraversal() {
postorderTraversal(root);
}
private void postorderTraversal(TreeNode node) {
if (node!= null) {
postorderTraversal(node.left);
postorderTraversal(node.right);
System.out.print(node.val + " ");
}
}
// 层序遍历:按层次从上到下,从左到右遍历
public void levelOrderTraversal() {
if (root == null) {
return;
}
java.util.LinkedList<TreeNode> queue = new java.util.LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
System.out.print(node.val + " ");
if (node.left!= null) {
queue.add(node.left);
}
if (node.right!= null) {
queue.add(node.right);
}
}
}
// 插入节点(简单示例,这里只是插入到空的根节点)
public void insert(int val) {
if (root == null) {
root = new TreeNode(val);
} else {
// 更复杂的插入逻辑可根据具体需求实现
// 这里暂不处理
}
}
}
你可以使用以下方式测试这些方法:
public class Main {
public static void main(String[] args) {
BinaryTree binaryTree = new BinaryTree();
binaryTree.insert(1);
binaryTree.insert(2);
binaryTree.insert(3);
binaryTree.insert(4);
binaryTree.insert(5);
System.out.println("前序遍历结果: ");
binaryTree.preorderTraversal();
System.out.println("\n中序遍历结果: ");
binaryTree.inorderTraversal();
System.out.println("\n后序遍历结果: ");
binaryTree.postorderTraversal();
System.out.println("\n层序遍历结果: ");
binaryTree.levelOrderTraversal();
}
}
八.图
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
// 图节点类
class GraphNode {
int val;
List<GraphNode> neighbors;
GraphNode(int val) {
this.val = val;
this.neighbors = new ArrayList<>();
}
}
// 图操作类
class GraphUtils {
// 深度优先搜索
public static void dfs(GraphNode node, boolean[] visited) {
if (visited[node.val]) return;
visited[node.val] = true;
System.out.print(node.val + " ");
for (GraphNode neighbor : node.neighbors) {
if (!visited[neighbor.val]) {
dfs(neighbor, visited);
}
}
}
// 广度优先搜索
public static void bfs(GraphNode start) {
boolean[] visited = new boolean[100];
Queue<GraphNode> queue = new LinkedList<>();
queue.add(start);
visited[start.val] = true;
while (!queue.isEmpty()) {
GraphNode node = queue.poll();
System.out.print(node.val + " ");
for (GraphNode neighbor : node.neighbors) {
if (!visited[neighbor.val]) {
visited[neighbor.val] = true;
queue.add(neighbor);
}
}
}
}
// 添加边
public static void addEdge(GraphNode node1, GraphNode node2) {
node1.neighbors.add(node2);
node2.neighbors.add(node1);
}
}
public class Main {
public static void main(String[] args) {
GraphNode node1 = new GraphNode(1);
GraphNode node2 = new GraphNode(2);
GraphNode node3 = new GraphNode(3);
GraphNode node4 = new GraphNode(4);
GraphUtils.addEdge(node1, node2);
GraphUtils.addEdge(node1, node3);
GraphUtils.addEdge(node2, node4);
boolean[] visited = new boolean[100];
System.out.println("深度优先搜索结果:");
GraphUtils.dfs(node1, visited);
System.out.println("\n广度优先搜索结果:");
GraphUtils.bfs(node1);
}
}
在Java中,图是一种复杂的数据结构,常用的图操作可以基于 java.util 包下的 List 和 Map 等集合类来实现。以下是一些图常用的Java方法示例:
上述代码中, GraphNode 类表示图的节点, GraphUtils 类包含了图的一些常用操作方法,如深度优先搜索、广度优先搜索和添加边的方法。最后通过 Main 类的 main 方法进行了测试。
九.堆
以下是在Java中堆(以二叉堆为例)常用的方法及示例代码:
import java.util.ArrayList;
import java.util.List;
// 二叉堆类
class BinaryHeap {
private List<Integer> heap;
// 构造函数,初始化堆
public BinaryHeap() {
heap = new ArrayList<>();
}
// 插入元素
public void insert(int value) {
heap.add(value);
int currentIndex = heap.size() - 1;
int parentIndex = (currentIndex - 1) / 2;
// 上浮调整
while (currentIndex > 0 && heap.get(currentIndex) < heap.get(parentIndex)) {
swap(currentIndex, parentIndex);
currentIndex = parentIndex;
parentIndex = (currentIndex - 1) / 2;
}
}
// 删除堆顶元素(最小值)
public int deleteMin() {
if (heap.isEmpty()) {
throw new IllegalStateException("堆为空");
}
int min = heap.get(0);
// 将最后一个元素移到堆顶
heap.set(0, heap.get(heap.size() - 1));
heap.remove(heap.size() - 1);
// 下沉调整
int currentIndex = 0;
int leftChildIndex = 2 * currentIndex + 1;
int rightChildIndex = 2 * currentIndex + 2;
while (leftChildIndex < heap.size()) {
int minChildIndex = leftChildIndex;
// 找到左右子节点中的较小值
if (rightChildIndex < heap.size() && heap.get(rightChildIndex) < heap.get(leftChildIndex)) {
minChildIndex = rightChildIndex;
}
// 如果当前节点大于最小子节点,则交换
if (heap.get(currentIndex) > heap.get(minChildIndex)) {
swap(currentIndex, minChildIndex);
currentIndex = minChildIndex;
leftChildIndex = 2 * currentIndex + 1;
rightChildIndex = 2 * currentIndex + 2;
} else {
break;
}
}
return min;
}
// 获取堆顶元素
public int peek() {
if (heap.isEmpty()) {
throw new IllegalStateException("堆为空");
}
return heap.get(0);
}
// 交换堆中两个元素的位置
private void swap(int i, int j) {
int temp = heap.get(i);
heap.set(i, heap.get(j));
heap.set(j, temp);
}
}
你可以使用以下方式测试这些方法:
public class Main {
public static void main(String[] args) {
BinaryHeap heap = new BinaryHeap();
heap.insert(5);
heap.insert(3);
heap.insert(7);
heap.insert(2);
heap.insert(4);
System.out.println("堆顶元素: " + heap.peek());
System.out.println("删除堆顶元素: " + heap.deleteMin());
System.out.println("堆顶元素: " + heap.peek());
}
}
上述代码实现了一个最小堆,包含插入元素、删除堆顶元素、获取堆顶元素等常用方法。在插入元素后,通过上浮调整来维护堆的性质;删除堆顶元素后,通过下沉调整来重新构建堆。