2024-08-15



package main
 
import (
    "fmt"
)
 
// 定义一个泛型接口,包含两个类型参数 T1 和 T2
type GenericInterface[T1, T2 any] interface {
    Method1(a T1, b T2) T1
    Method2(a T1, b T2) T2
}
 
// 实现泛型接口的具体类型
type ConcreteType[T1, T2 any] struct {
    field1 T1
    field2 T2
}
 
// 为 ConcreteType 实现 GenericInterface 接口
func (c ConcreteType[T1, T2]) Method1(a T1, b T2) T1 {
    return a
}
 
func (c ConcreteType[T1, T2]) Method2(a T1, b T2) T2 {
    return b
}
 
func main() {
    // 创建一个 ConcreteType 实例
    var generic GenericInterface[string, int] = ConcreteType[string, int]{
        field1: "Hello",
        field2: 42,
    }
 
    // 使用泛型接口的方法
    result1 := generic.Method1("World", 24)
    result2 := generic.Method2("World", 24)
 
    fmt.Println(result1, result2) // 输出: World 24
}

这段代码定义了一个泛型接口GenericInterface,它有两个类型参数T1T2,以及两个方法Method1Method2。然后定义了一个具体类型ConcreteType,它实现了这个泛型接口。在main函数中,我们创建了ConcreteType的一个实例,并展示了如何使用泛型接口的方法。这个例子简单直观地展示了如何在Go中使用泛型接口。

2024-08-14

在Java中,List接口和ArrayList类是用于存储一系列元素的集合框架。List是一个接口,而ArrayList是List接口的一个可动态扩展的数组实现。

以下是一些基本操作的示例代码:

  1. 创建一个ArrayList:



ArrayList<String> arrayList = new ArrayList<>();
  1. 添加元素到ArrayList:



arrayList.add("Element 1");
arrayList.add("Element 2");
  1. 获取ArrayList中的元素:



String element = arrayList.get(0); //获取第一个元素
  1. 修改ArrayList中的元素:



arrayList.set(0, "Element 100"); //将第一个元素修改为"Element 100"
  1. 删除ArrayList中的元素:



arrayList.remove(0); //删除第一个元素
  1. 获取ArrayList的大小:



int size = arrayList.size();
  1. 遍历ArrayList中的元素:



for (String element : arrayList) {
    System.out.println(element);
}

或者使用迭代器:




Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

以上代码展示了如何在Java中创建和操作一个ArrayList。

2024-08-14



public class MinHeap<T extends Comparable<T>> {
    private ArrayList<T> list;
 
    public MinHeap() {
        list = new ArrayList<>();
    }
 
    // 向堆中插入元素
    public void insert(T element) {
        list.add(element);
        siftUp(list.size() - 1);
    }
 
    // 从堆中取出最小元素
    public T extractMin() {
        if (list.isEmpty()) return null;
        T min = list.get(0);
        list.set(0, list.get(list.size() - 1));
        list.remove(list.size() - 1);
        siftDown(0);
        return min;
    }
 
    // 获取堆顶元素但不移除它
    public T getMin() {
        if (list.isEmpty()) return null;
        return list.get(0);
    }
 
    // 调整元素以满足堆的性质,向上调整
    private void siftUp(int index) {
        while (index > 0) {
            int parent = (index - 1) / 2;
            if (list.get(parent).compareTo(list.get(index)) <= 0) break;
            Collections.swap(list, parent, index);
            index = parent;
        }
    }
 
    // 调整元素以满足堆的性质,向下调整
    private void siftDown(int index) {
        int half = list.size() / 2;
        while (index < half) {
            // 找到子节点中较小的一个
            int child = (index * 2) + 1;
            if (child + 1 < list.size() && list.get(child + 1).compareTo(list.get(child)) < 0)
                child++;
            if (list.get(index).compareTo(list.get(child)) <= 0) break;
            Collections.swap(list, index, child);
            index = child;
        }
    }
 
    // 获取堆中元素的数量
    public int size() {
        return list.size();
    }
 
    // 判断堆是否为空
    public boolean isEmpty() {
        return list.isEmpty();
    }
 
    // 主函数,用于测试堆的创建和使用
    public static void main(String[] args) {
        MinHeap<Integer> minHeap = new MinHeap<>();
        int[] data = {10, 5, 15, 8, 20, 6};
 
        // 插入元素到堆中
        for (int num : data) {
            minHeap.insert(num);
        }
 
        // 获取最小的k个数
        int k = 3;
        for (int i = 0; i < k; i++) {
            System.out.println(minHeap.extractMin());
        }
    }
}

这段代码实现了一个最小堆,并展示了如何使用它来解决 TOP-K 问题。在主函数中,我们创建了一个最小堆并插入了一些数据,然后连续提取最小的 k 个数。这个过程模拟了堆的应用场景,对于学习数据结构和算法的学生来说具有很好的教育价值。

2024-08-14



public class BST<Key extends Comparable<Key>, Value> {
 
    private Node root; // 根节点
 
    private class Node {
        private Key key; // 键
        private Value value; // 值
        private Node left, right; // 左右子节点
        private int N; // 以此节点为根的子树中的节点总数
 
        public Node(Key key, Value value, int N) {
            this.key = key;
            this.value = value;
            this.N = N;
        }
    }
 
    // 获取二叉搜索树中的节点个数
    public int size() {
        return size(root);
    }
 
    // 递归方式获取节点个数
    private int size(Node x) {
        if (x == null) {
            return 0;
        } else {
            return x.N;
        }
    }
 
    // 二叉搜索树的最小键值
    public Key min() {
        return min(root).key;
    }
 
    // 递归方式获取最小键值
    private Node min(Node x) {
        if (x.left == null) {
            return x;
        }
        return min(x.left);
    }
 
    // 二叉搜索树的最大键值
    public Key max() {
        return max(root).key;
    }
 
    // 递归方式获取最大键值
    private Node max(Node x) {
        if (x.right == null) {
            return x;
        }
        return max(x.right);
    }
 
    // 向二叉搜索树中插入键值对
    public void put(Key key, Value value) {
        root = put(root, key, value);
    }
 
    // 递归方式向二叉搜索树中插入键值对
    private Node put(Node x, Key key, Value value) {
        if (x == null) {
            return new Node(key, value, 1);
        }
        int cmp = key.compareTo(x.key);
        if (cmp < 0) {
            x.left = put(x.left, key, value);
        } else if (cmp > 0) {
            x.right = put(x.right, key, value);
        } else {
            x.value = value;
        }
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }
 
    // 从二叉搜索树中删除键值
    public void delete(Key key) {
        root = delete(root, key);
    }
 
    // 递归方式从二叉搜索树中删除键值
    private Node delete(Node x, Key key) {
        if (x == null) {
            return null;
        }
        int cmp = key.compareTo(x.key);
        if (cmp < 0) {
            x.left = delete(x.left, key);
        } else if (cmp > 0) {
            x.right = delete(x.right, key);
        } else {
            if (x.right == null) {
                return x.left;
            }
            if (x.left == null) {
                return x.right;
            }
            Node t = x;
            x = min(t.right);
            x.rig
2024-08-14

栈(Stack)和队列(Queue)是两种重要的线性数据结构,它们在计算机科学中有着广泛的应用,比如在编译器设计、操作系统进程管理、游戏等领域中作为基础数据结构使用。

以下是使用Java实现栈和队列的简单示例:

栈的实现:




public class Stack<T> {
    private java.util.List<T> list = new ArrayList<>();
 
    // 入栈
    public void push(T item) {
        list.add(item);
    }
 
    // 出栈
    public T pop() {
        if (list.isEmpty()) {
            return null;
        }
        return list.remove(list.size() - 1);
    }
 
    // 查看栈顶元素
    public T peek() {
        if (list.isEmpty()) {
            return null;
        }
        return list.get(list.size() - 1);
    }
 
    // 判断栈是否为空
    public boolean isEmpty() {
        return list.isEmpty();
    }
}

队列的实现:




public class Queue<T> {
    private java.util.List<T> list = new ArrayList<>();
 
    // 入队
    public void enqueue(T item) {
        list.add(item);
    }
 
    // 出队
    public T dequeue() {
        if (list.isEmpty()) {
            return null;
        }
        return list.remove(0);
    }
 
    // 查看队首元素
    public T peek() {
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }
 
    // 判断队列是否为空
    public boolean isEmpty() {
        return list.isEmpty();
    }
}

在上述代码中,我们使用了Java的ArrayList来存储栈和队列的元素。pushpoppeek分别用于进行入栈、出栈和查看栈顶元素的操作,对应先入后出的特性。enqueuedequeuepeek同样用于进行入队、出队和查看队首元素的操作,对应先入先出的特性。isEmpty方法用于检查栈或队列是否为空。

2024-08-14

JavaScript中的Set是一种新的原生集合类型,类似于数组,但只能有唯一的值。

以下是一些Set的常用方法和操作:

  1. 创建Set



let s = new Set();
  1. 添加元素



s.add(1);
s.add("hello");
  1. 删除元素



s.delete(1);
  1. 检查元素是否存在



s.has(1); // false
  1. 清空Set



s.clear();
  1. 获取Set的长度



s.size;
  1. 遍历Set



for (let item of s) {
    console.log(item);
}
  1. 使用Array去重



let arr = [1, 2, 3, 2, 4, 1];
let unique = [...new Set(arr)];
  1. 交集、并集、差集操作



let setA = new Set([1, 2, 3]);
let setB = new Set([2, 3, 4]);
 
// 并集
let union = new Set([...setA, ...setB]);
 
// 交集
let intersect = new Set([...setA].filter(x => setB.has(x)));
 
// 差集
let difference = new Set([...setA].filter(x => !setB.has(x)));

以上是Set的基本操作和使用方法,Set是一种新的数据结构,可以用于解决一些实际问题,例如,数组去重、数据的交集、并集、差集等操作。

2024-08-13

在Java中,PriorityQueue是一个基于堆实现的无界队列。每次从队列中提取元素都是提取最小(或最大)元素,这就是为什么它被称为优先级队列。

下面是如何使用PriorityQueue的示例代码:




import java.util.PriorityQueue;
 
public class PriorityQueueExample {
    public static void main(String[] args) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
 
        // 添加元素
        priorityQueue.offer(30);
        priorityQueue.offer(10);
        priorityQueue.offer(20);
 
        // 查看队首元素
        System.out.println("Front element: " + priorityQueue.peek()); // 输出:Front element: 10
 
        // 移除并返回队首元素
        System.out.println("Removed element: " + priorityQueue.poll()); // 输出:Removed element: 10
 
        // 判断队列是否为空
        System.out.println("Is queue empty? " + priorityQueue.isEmpty()); // 输出:Is queue empty? false
 
        // 清空队列
        priorityQueue.clear();
        System.out.println("Is queue empty after clearing? " + priorityQueue.isEmpty()); // 输出:Is queue empty after clearing? true
    }
}

在上述代码中,我们创建了一个PriorityQueue,向其中添加了几个整数。我们使用peek()方法来查看队首元素,使用poll()方法来移除并返回队首元素。我们还检查了队列是否为空,并清空了队列。

堆(Heap)是一个具有特殊属性的完全二叉树:每个节点的值都大于或等于(或小于或等于)其子节点的值,称为最大堆或最小堆。在Java中,PriorityQueue内部就是通过堆来实现的。

堆通常用于实现优先队列,还可以用于排序等操作。但是,在Java的标准库中,堆的直接操作相对较少,因为PriorityQueue已经提供了相同的功能,并且使用更方便。因此,在实际编程中,堆的直接操作通常会使用PriorityQueue

2024-08-13

ArrayList是Java集合框架中的一部分,是一种可动态增长和减小的数组。

以下是一些常用的ArrayList方法:

  1. 添加元素:



ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("Apple");
arrayList.add("Banana");
  1. 在指定位置添加元素:



arrayList.add(1, "Orange");
  1. 删除元素:



arrayList.remove("Apple");
  1. 在指定位置删除元素:



arrayList.remove(1);
  1. 修改元素:



arrayList.set(1, "Mango");
  1. 获取元素:



String fruit = arrayList.get(1);
  1. 获取ArrayList大小:



int size = arrayList.size();
  1. 判断ArrayList是否为空:



boolean isEmpty = arrayList.isEmpty();
  1. 清空ArrayList:



arrayList.clear();
  1. 遍历ArrayList:



for (String fruit : arrayList) {
    System.out.println(fruit);
}

或者使用迭代器:




Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

这些是ArrayList的基本操作,具体使用时可以根据需要选择相应的方法。

2024-08-12

栈(Stack)是一种线性数据结构,遵循后进先出(LIFO)原则。在Java中,我们可以使用标准库中的Stack类,也可以自己实现一个栈。以下是一个简单的自定义栈的示例:




public class MyStack<T> {
    private List<T> list;
 
    public MyStack() {
        list = new ArrayList<>();
    }
 
    // 入栈
    public void push(T item) {
        list.add(item);
    }
 
    // 出栈
    public T pop() {
        if (list.isEmpty()) {
            return null;
        }
        return list.remove(list.size() - 1);
    }
 
    // 查看栈顶元素
    public T peek() {
        if (list.isEmpty()) {
            return null;
        }
        return list.get(list.size() - 1);
    }
 
    // 判断栈是否为空
    public boolean isEmpty() {
        return list.isEmpty();
    }
}
 
// 使用示例
public class StackExample {
    public static void main(String[] args) {
        MyStack<Integer> stack = new MyStack<>();
 
        // 入栈
        stack.push(1);
        stack.push(2);
        stack.push(3);
 
        // 查看栈顶元素
        System.out.println("栈顶元素: " + stack.peek()); // 输出: 栈顶元素: 3
 
        // 出栈两次
        stack.pop();
        stack.pop();
 
        // 再次查看栈顶元素
        System.out.println("栈顶元素: " + stack.peek()); // 输出: 栈顶元素: 1
 
        // 判断栈是否为空
        System.out.println("栈是否为空: " + stack.isEmpty()); // 输出: 栈是否为空: false
    }
}

在这个示例中,我们定义了一个泛型类MyStack,它具有入栈(push)、出栈(pop)、查看栈顶元素(peek)以及判断栈是否为空(isEmpty)的基本操作。然后,我们创建了一个StackExample类来演示如何使用MyStack

2024-08-11



package main
 
import (
    "fmt"
    "github.com/emirpasic/gods"
    "github.com/emirpasic/gods/lists/singlylinkedlist"
)
 
func main() {
    // 创建一个单向链表
    list := singlylinkedlist.New()
 
    // 往链表中添加元素
    list.Add(1)
    list.Add("a")
    list.Add(2)
    list.Add("b")
 
    // 遍历链表并打印元素
    for i := 0; i < list.Size(); i++ {
        fmt.Println(list.Value(i))
    }
 
    // 使用迭代器来遍历链表
    iterator := list.Iterator()
    for iterator.Next() {
        fmt.Println(iterator.Value())
    }
}

这段代码演示了如何使用singlylinkedlist库创建一个单向链表,并展示了如何添加元素、遍历链表以及使用迭代器进行遍历。这是一个简单的数据结构示例,对于学习Go语言中的算法和数据结构有很好的教育意义。