从0开始学算法——第三天(数据结构的操作)

写在开头的话

数据结构有许多常见的操作,这些操作用于在数据结构中插入、删除、搜索或者遍历元素。本文将会为大家介绍各类数据结构的操作与使用,同时也会通过实战,带领大家领略数据结构的魅力。

知识点:

(1)扩容数组的操作(2)链表的操作(3)栈的操作(4)队列的操作(5)集合的操作(6)哈希表的操作(7)树的操作(8)图的操作

1.扩容数组的操作

在 C++、Java 和 Python 中,扩容数组通常是通过动态数组的方式实现的,具体细节略有不同。扩容的大致思路均是重新创建一个新数组,然后新数组的大小比原数组大,然后将原数组复制的新数组中,下面是它们的简单介绍 :

C++

在 C++ 中,可以使用 std::vector 来创建动态数组,当向 std::vector 添加元素时,如果元素数量超过了当前容量,std::vector 会自动扩容以容纳更多的元素。它会重新分配一块更大的内存空间,然后将原来的元素复制到新的空间中,然后释放原来的空间。

C++代码实现

cpp 复制代码
#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec;

    // 添加元素
    for(int i = 0; i < 10; ++i) {
        vec.push_back(i);
    }

    std::cout << "Size: " << vec.size() << std::endl;
    std::cout << "Capacity: " << vec.capacity() << std::endl;

    return 0;
}

Java

在 Java 中,可以使用 ArrayList 来创建动态数组。当向 ArrayList 添加元素时,如果元素数量超过了当前容量,ArrayList 会自动扩容。它会创建一个新的数组,将原来的元素复制到新的数组中,然后将新数组作为其内部数组。

Java代码实现

java 复制代码
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();

        // 添加元素
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }

        System.out.println("Size: " + list.size());
        System.out.println("Capacity: " + list.toArray().length);
    }
}

Python

在 Python 中,可以使用 list 来创建动态数组。当向 list 添加元素时,如果元素数量超过了当前容量,list 会自动扩容。它会重新分配一块更大的内存空间,将原来的元素复制到新的空间中,然后释放原来的空间。

Python代码实现

python 复制代码
arr = []

# 添加元素
for i in range(10):
    arr.append(i)

print("Size:", len(arr))
print("Capacity:", arr.__sizeof__())

这些是常见的方式来创建动态数组,它们会自动处理数组容量的扩展,使得在向数组中添加大量元素时不需要手动管理内存空间。

运行结果

2.链表的操作

对于链表,我们可以手动实现链表与利用编程语言现成的代码库实现链表。

手动实现链表是指在编程语言中,通过定义节点结构和编写操作节点的函数来创建和操作链表。这种方法需要程序员自己管理节点的内存分配和释放,包括节点的链接和断开。通常会涉及到指针的使用,需要小心处理以避免内存泄漏或者指针错误。

利用代码库实现链表是指使用编程语言提供的现成的数据结构或库来创建和操作链表。例如在 C++ 中使用 std::list、Java 中使用 java.util.LinkedList、Python 中使用 collections.deque 等。这些数据结构提供了一组现成的接口函数,可以方便地进行插入、删除、遍历等操作,同时也会自动处理内存的分配和释放。

简单来说,链表的原理就是定义一个节点,节点分为指针域和值域,指针域存放其他节点的地址(引用),值域存放我们的值。

手动实现链表

C++

在 C++ 中,可以使用指针来创建和操作链表。链表是一种线性数据结构,由节点 (Node) 组成,每个节点包含数据和指向下一个节点的指针。C++ 中的链表通常是通过手动分配内存来创建的,需要注意释放节点的内存以避免内存泄漏。

C++代码实现

cpp 复制代码
#include <iostream>

struct Node {
    int data;
    Node* next;
};

int main() {
    // 创建节点
    Node* head = new Node;
    head->data = 1;

    Node* second = new Node;
    second->data = 2;

    Node* third = new Node;
    third->data = 3;

    // 构建链表
    head->next = second;
    second->next = third;
    third->next = nullptr;

    // 遍历链表
    Node* current = head;
    while (current != nullptr) {
        std::cout << current->data << " ";
        current = current->next;
    }

    // 释放内存
    delete head;
    delete second;
    delete third;

    return 0;
}

Java

在 Java 中,可以使用 Node 类和引用来创建链表。Java 的链表通常是作为 Node 类的对象之间的连接来表示的。

Java代码实现

java 复制代码
public class Node {
    int data;
    Node next;

    public Node(int data) {
        this.data = data;
        this.next = null;
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建节点
        Node head = new Node(1);
        Node second = new Node(2);
        Node third = new Node(3);

        // 构建链表
        head.next = second;
        second.next = third;
        third.next = null;

        // 遍历链表
        Node current = head;
        while (current != null) {
            System.out.print(current.data + " ");
            current = current.next;
        }
    }
}

Python

在 Python 中,可以使用类来创建链表,类似于 Java 的方式。Python 的链表可以使用类来表示节点之间的连接关系。

Python代码实现

python 复制代码
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

# 创建节点
head = Node(1)
second = Node(2)
third = Node(3)

# 构建链表
head.next = second
second.next = third
third.next = None

# 遍历链表
current = head
while current is not None:
    print(current.data, end=" ")
    current = current.next

以上是使用 C++、Java 和 Python 创建和操作简单链表的示例。链表是一种灵活的数据结构,可用于有效地存储和操作数据。

运行结果

利用代码库实现链表

C++ (使用标准库 std::list)

在 C++ 中,可以使用标准库中的 std::list 来创建链表。std::list 是一个双向链表,它提供了方便的操作函数,如插入、删除和遍历等。

C++代码实现

cpp 复制代码
#include <iostream>
#include <list>

int main() {
    // 创建一个 std::list 对象
    std::list<int> myLinkedList;

    // 在链表末尾添加元素
    myLinkedList.push_back(1);
    myLinkedList.push_back(2);
    myLinkedList.push_back(3);

    // 在链表开头插入元素
    myLinkedList.push_front(0);

    // 遍历链表并输出元素
    for (int val : myLinkedList) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    // 在指定位置插入元素
    auto it = std::next(myLinkedList.begin(), 2); // 获取第3个位置的迭代器
    myLinkedList.insert(it, 10);

    // 删除指定位置的元素
    it = std::next(myLinkedList.begin(), 1); // 获取第2个位置的迭代器
    myLinkedList.erase(it);

    // 输出修改后的链表
    for (int val : myLinkedList) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

Java (使用 java.util.LinkedList)

在 Java 中,可以使用 java.util.LinkedList 来创建链表。LinkedList 是一个双向链表实现,提供了方便的方法来添加、删除和遍历元素。

Java代码实现

java 复制代码
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        // 创建一个 LinkedList 对象
        LinkedList<Integer> myLinkedList = new LinkedList<>();

        // 在链表末尾添加元素
        myLinkedList.add(1);
        myLinkedList.add(2);
        myLinkedList.add(3);

        // 在链表开头插入元素
        myLinkedList.addFirst(0);

        // 遍历链表并输出元素
        for (int val : myLinkedList) {
            System.out.print(val + " ");
        }
        System.out.println();

        // 在指定位置插入元素
        myLinkedList.add(2, 10);

        // 删除指定位置的元素
        myLinkedList.remove(1);

        // 输出修改后的链表
        for (int val : myLinkedList) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}

Python (使用 collections.deque)

在 Python 中,可以使用 collections.deque 来创建双端队列,也可以用它来实现链表的功能。collections.deque 是一个双向队列,可以在头部和尾部高效地添加和删除元素。

Python代码实现

python 复制代码
from collections import deque

# 创建一个 deque 对象
my_linked_list = deque()

# 在链表末尾添加元素
my_linked_list.append(1)
my_linked_list.append(2)
my_linked_list.append(3)

# 在链表开头插入元素
my_linked_list.appendleft(0)

# 遍历链表并输出元素
for val in my_linked_list:
    print(val, end=" ")
print()

# 在指定位置插入元素(不支持直接插入,需要先将其转换为列表操作)
my_linked_list.insert(2, 10)

# 删除指定位置的元素(同样需要先转换为列表操作)
del my_linked_list[1]

# 输出修改后的链表
for val in my_linked_list:
    print(val, end=" ")
print()

以上是使用 C++ 的 std::list、Java 的 java.util.LinkedList 和 Python 的 collections.deque 创建和操作链表的示例。这些标准库提供了方便的接口和功能,可以轻松地实现链表的常见操作。

运行结果

3.栈的操作

栈通常具有两个基本操作 :

  • 入栈 (push) :将新元素添加到栈顶。
  • 出栈 (pop) :从栈顶移除元素。

栈常用于许多算法和程序设计中,如函数调用、表达式求值、内存管理等。

手动实现栈

手动实现栈是指在编程语言中,通过定义栈结构和编写操作栈的函数来创建和操作栈。这种方法需要程序员自己管理栈内元素的添加、移除和检查,同时需要处理栈空间的分配和释放。

C++代码实现

cpp 复制代码
#include <iostream>

#define MAX_SIZE 100

class Stack {
private:
    int top;
    int data[MAX_SIZE];

public:
    Stack() {
        top = -1;
    }

    bool isEmpty() {
        return top == -1;
    }

    bool isFull() {
        return top == MAX_SIZE - 1;
    }

    void push(int value) {
        if (isFull()) {
            std::cout << "Stack overflow! Cannot push element " << value << std::endl;
            return;
        }
        top++;
        data[top] = value;
    }

    void pop() {
        if (isEmpty()) {
            std::cout << "Stack underflow! Cannot pop from an empty stack." << std::endl;
            return;
        }
        top--;
    }

    int peek() {
        if (isEmpty()) {
            std::cout << "Stack is empty." << std::endl;
            return -1; // or throw an exception
        }
        return data[top];
    }
};

int main() {
    Stack myStack;

    // 入栈操作
    myStack.push(10);
    myStack.push(20);
    myStack.push(30);

    // 获取栈顶元素
    std::cout << "Top element: " << myStack.peek() << std::endl;

    // 出栈操作
    myStack.pop();

    // 再次获取栈顶元素
    std::cout << "Top element after pop: " << myStack.peek() << std::endl;

    return 0;
}

Java代码实现

java 复制代码
class Stack {
    private int top;
    private int[] data;
    private int maxSize;

    public Stack(int size) {
        maxSize = size;
        data = new int[maxSize];
        top = -1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public void push(int value) {
        if (isFull()) {
            System.out.println("Stack overflow! Cannot push element " + value);
            return;
        }
        top++;
        data[top] = value;
    }

    public void pop() {
        if (isEmpty()) {
            System.out.println("Stack underflow! Cannot pop from an empty stack.");
            return;
        }
        top--;
    }

    public int peek() {
        if (isEmpty()) {
            System.out.println("Stack is empty.");
            return -1; // or throw an exception
        }
        return data[top];
    }
}

public class Main {
    public static void main(String[] args) {
        Stack myStack = new Stack(100);

        // 入栈操作
        myStack.push(10);
        myStack.push(20);
        myStack.push(30);

        // 获取栈顶元素
        System.out.println("Top element: " + myStack.peek());

        // 出栈操作
        myStack.pop();

        // 再次获取栈顶元素
        System.out.println("Top element after pop: " + myStack.peek());
    }
}

Python代码实现

python 复制代码
class Stack:
    def __init__(self):
        self.data = []

    def is_empty(self):
        return len(self.data) == 0

    def push(self, value):
        self.data.append(value)

    def pop(self):
        if self.is_empty():
            print("Stack underflow! Cannot pop from an empty stack.")
            return
        self.data.pop()

    def peek(self):
        if self.is_empty():
            print("Stack is empty.")
            return -1  # or raise an exception
        return self.data[-1]

# 创建栈对象
my_stack = Stack()

# 入栈操作
my_stack.push(10)
my_stack.push(20)
my_stack.push(30)

# 获取栈顶元素
print("Top element:", my_stack.peek())

# 出栈操作
my_stack.pop()

# 再次获取栈顶元素
print("Top element after pop:", my_stack.peek())

以上是使用 C++、Java 和 Python 手动实现栈的示例代码。这些示例展示了如何定义栈结构,并实现了栈的基本操作,包括入栈、出栈、获取栈顶元素等。

运行结果

利用代码库实现栈

C++ (STL std::stack)

在 C++ 中,可以使用标准模板库(STL)中的 std::stack 来实现栈。std::stack 提供了一种简单且高效的方式来操作栈,包括入栈 (push)、出栈 (pop)、获取栈顶元素 (top) 等操作。

C++代码实现

cpp 复制代码
#include <iostream>
#include <stack>

int main() {
    // 创建一个 std::stack 对象
    std::stack<int> myStack;

    // 入栈操作
    myStack.push(10);
    myStack.push(20);
    myStack.push(30);

    // 获取栈顶元素
    std::cout << "Top element: " << myStack.top() << std::endl;

    // 出栈操作
    myStack.pop();

    // 再次获取栈顶元素
    std::cout << "Top element after pop: " << myStack.top() << std::endl;

    return 0;
}

Java (java.util.Stack)

在 Java 中,可以使用 java.util.Stack 类来实现栈。java.util.Stack 继承自 Vector 类,提供了一系列的入栈 (push)、出栈 (pop)、获取栈顶元素 (peek) 等方法。、

Java代码实现

java 复制代码
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        // 创建一个 Stack 对象
        Stack<Integer> myStack = new Stack<>();

        // 入栈操作
        myStack.push(10);
        myStack.push(20);
        myStack.push(30);

        // 获取栈顶元素
        System.out.println("Top element: " + myStack.peek());

        // 出栈操作
        myStack.pop();

        // 再次获取栈顶元素
        System.out.println("Top element after pop: " + myStack.peek());
    }
}

Python (collections.deque)

在 Python 中,可以使用 collections.deque 来实现栈。collections.deque 是 Python 标准库中的双端队列实现,可以方便地用作栈。

Python代码实现

python 复制代码
from collections import deque

# 创建一个 deque 对象
my_stack = deque()

# 入栈操作
my_stack.append(10)
my_stack.append(20)
my_stack.append(30)

# 获取栈顶元素
print("Top element:", my_stack[-1])

# 出栈操作
my_stack.pop()

# 再次获取栈顶元素
print("Top element after pop:", my_stack[-1])

以上是使用 C++ 的 std::stack、Java 的 java.util.Stack 和 Python 的 collections.deque 实现栈的示例代码。这些自带的库提供了简单且高效的方式来操作栈,无需手动管理内存,适用于大多数栈操作的需求。

运行结果

4.队列的操作

队列通常具有以下基本操作 :

  • 入队 (enqueue) :向队尾添加新元素。
  • 出队 (dequeue) :从队头移除元素。
  • 获取队头元素 (front) :返回队头元素,但不移除。
  • 判空 (isEmpty) :检查队列是否为空。
  • 判满 (isFull) :检查队列是否已满。

手动实现队列需要自行定义队列的数据结构和操作函数。这种方法涉及管理队列的底层数组、队首和队尾指针等细节。入队操作将新元素添加到队尾,出队操作从队头移除元素,获取队头元素则返回队列的第一个元素。这种方式需要程序员自己处理边界情况,如队列满时无法入队、队列空时无法出队等。

利用代码库实现队列则更加简单和方便。在 C++ 中,可以使用 std::queue,Java 中使用 java.util.Queue,Python 中使用 queue.Queue。这些库提供了现成的队列实现,包含了常用的入队、出队、获取队头元素等操作,无需手动管理底层细节。只需创建队列对象,即可直接使用这些库中提供的方法进行队列操作。这种方式更加高效,不必担心底层数据结构的实现细节,适用于大多数场景下的队列需求。

手动实现队列

C++代码实现

cpp 复制代码
#include <iostream>

#define MAX_SIZE 100

class Queue {
private:
    int front, rear;
    int data[MAX_SIZE];

public:
    Queue() {
        front = rear = -1;
    }

    // 判断队列是否为空
    bool isEmpty() {
        return front == -1;
    }

    // 判断队列是否已满
    bool isFull() {
        return rear == MAX_SIZE - 1;
    }

    // 入队操作
    void enqueue(int value) {
        if (isFull()) {
            std::cout << "Queue is full. Cannot enqueue element " << value << std::endl;
            return;
        }

        if (isEmpty()) {
            front = 0;
        }

        rear++;
        data[rear] = value;
    }

    // 出队操作
    void dequeue() {
        if (isEmpty()) {
            std::cout << "Queue is empty. Cannot dequeue." << std::endl;
            return;
        }

        if (front == rear) {
            front = rear = -1;
        } else {
            front++;
        }
    }

    // 获取队头元素
    int getFront() {
        if (isEmpty()) {
            std::cout << "Queue is empty." << std::endl;
            return -1;
        }
        return data[front];
    }
};

Java代码实现

java 复制代码
public class Queue {
    private int front, rear;
    private int[] data;
    private int capacity;

    public Queue(int capacity) {
        this.capacity = capacity;
        this.data = new int[capacity];
        this.front = this.rear = -1;
    }

    // 判断队列是否为空
    public boolean isEmpty() {
        return front == -1;
    }

    // 判断队列是否已满
    public boolean isFull() {
        return rear == capacity - 1;
    }

    // 入队操作
    public void enqueue(int value) {
        if (isFull()) {
            System.out.println("Queue is full. Cannot enqueue element " + value);
            return;
        }

        if (isEmpty()) {
            front = 0;
        }

        rear++;
        data[rear] = value;
    }

    // 出队操作
    public void dequeue() {
        if (isEmpty()) {
            System.out.println("Queue is empty. Cannot dequeue.");
            return;
        }

        if (front == rear) {
            front = rear = -1;
        } else {
            front++;
        }
    }

    // 获取队头元素
    public int getFront() {
        if (isEmpty()) {
            System.out.println("Queue is empty.");
            return -1;
        }
        return data[front];
    }
}

Python代码实现

python 复制代码
class Queue:
    def __init__(self, capacity):
        self.capacity = capacity
        self.data = [None] * capacity
        self.front = self.rear = -1

    # 判断队列是否为空
    def isEmpty(self):
        return self.front == -1

    # 判断队列是否已满
    def isFull(self):
        return self.rear == self.capacity - 1

    # 入队操作
    def enqueue(self, value):
        if self.isFull():
            print("Queue is full. Cannot enqueue element", value)
            return

        if self.isEmpty():
            self.front = 0

        self.rear += 1
        self.data[self.rear] = value

    # 出队操作
    def dequeue(self):
        if self.isEmpty():
            print("Queue is empty. Cannot dequeue.")
            return

        if self.front == self.rear:
            self.front = self.rear = -1
        else:
            self.front += 1

    # 获取队头元素
    def getFront(self):
        if self.isEmpty():
            print("Queue is empty.")
            return -1
        return self.data[self.front]

以上是手动实现队列的 Java、C++ 和 Python 示例代码。这些代码展示了队列的基本操作,包括入队 (enqueue)、出队 (dequeue)、判空 (isEmpty)、判满 (isFull) 和获取队头元素 (getFront) 等。可以根据需求进行适当的修改和扩展。

利用代码库实现队列

C++代码实现

cpp 复制代码
#include <iostream>
#include <queue>

int main() {
    // 创建一个队列对象
    std::queue<int> queue;

    // 入队操作
    queue.push(10);
    queue.push(20);
    queue.push(30);

    // 出队操作
    queue.pop();

    // 获取队头元素
    std::cout << "Front element: " << queue.front() << std::endl;

    // 获取队尾元素
    std::cout << "Back element: " << queue.back() << std::endl;

    return 0;
}

Java代码实现

java 复制代码
import java.util.LinkedList;
import java.util.Queue;

public class Main {
    public static void main(String[] args) {
        // 创建一个队列对象
        Queue<Integer> queue = new LinkedList<>();

        // 入队操作
        queue.offer(10);
        queue.offer(20);
        queue.offer(30);

        // 出队操作
        queue.poll();

        // 获取队头元素
        System.out.println("Front element: " + queue.peek());

        // 获取队尾元素(对于 Java 的 Queue 接口没有直接的方法,但可以通过转换成 LinkedList 来实现)
        LinkedList<Integer> linkedList = (LinkedList<Integer>) queue;
        System.out.println("Back element: " + linkedList.getLast());
    }
}

Python代码实现

python 复制代码
from queue import Queue

# 创建一个队列对象
queue = Queue()

# 入队操作
queue.put(10)
queue.put(20)
queue.put(30)

# 出队操作
queue.get()

# 获取队头元素
print("Front element:", queue.queue[0])

# 获取队尾元素(Python 的 Queue 没有直接的方法,但可以通过转换成列表来实现)
queue_list = list(queue.queue)
print("Back element:", queue_list[-1])

以上是使用代码库实现队列的 C++、Java 和 Python 示例代码。这些代码使用了各自语言的标准库提供的队列数据结构,分别是 C++ 的 std::queue、Java 的 java.util.Queue(实现类为 java.util.LinkedList)和 Python 的 queue.Queue。这些代码展示了队列的基本操作,包括入队 (push/offer/put)、出队 (pop/poll/get)、获取队头元素 (front/peek/queue[0]) 和获取队尾元素 (back/getLast/通过转换成列表取最后一个元素) 等。可以根据需求进行适当的修改和扩展。

运行结果

5.优先队列的操作

优先队列的定义

优先队列是一种特殊的队列,其中元素按照优先级顺序进行排列。与普通队列不同的是,优先队列中的元素可以根据优先级来获取,而不是按照它们进入队列的顺序。在优先队列中,元素通常是按照一定的规则进行排序的,例如按照数值大小、按照字典序等。

优先队列常见的实现方式

优先队列常见的实现方式包括堆、红黑树等数据结构。其中,堆是一种经典的实现方式,通常使用大根堆或小根堆来实现优先队列。大根堆中,父节点的值大于或等于其子节点的值;小根堆中,父节点的值小于或等于其子节点的值。

代码实现

C++代码实现

cpp 复制代码
#include <iostream>
#include <queue>

int main() {
    // 创建一个大根堆
    std::priority_queue<int> max_heap;

    // 插入元素
    max_heap.push(3);
    max_heap.push(1);
    max_heap.push(4);
    max_heap.push(1);
    max_heap.push(5);

    // 输出堆顶元素(最大值)
    std::cout << "Max element in max heap: " << max_heap.top() << std::endl;

    // 创建一个小根堆
    std::priority_queue<int, std::vector<int>, std::greater<int>> min_heap;

    // 插入元素
    min_heap.push(3);
    min_heap.push(1);
    min_heap.push(4);
    min_heap.push(1);
    min_heap.push(5);

    // 输出堆顶元素(最小值)
    std::cout << "Min element in min heap: " << min_heap.top() << std::endl;

    return 0;
}

Java代码实现

java 复制代码
import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        // 创建一个大根堆
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);

        // 插入元素
        maxHeap.offer(3);
        maxHeap.offer(1);
        maxHeap.offer(4);
        maxHeap.offer(1);
        maxHeap.offer(5);

        // 输出堆顶元素(最大值)
        System.out.println("Max element in max heap: " + maxHeap.peek());

        // 创建一个小根堆
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();

        // 插入元素
        minHeap.offer(3);
        minHeap.offer(1);
        minHeap.offer(4);
        minHeap.offer(1);
        minHeap.offer(5);

        // 输出堆顶元素(最小值)
        System.out.println("Min element in min heap: " + minHeap.peek());
    }
}

Python代码实现

python 复制代码
import heapq

# 创建一个大根堆
max_heap = []
# 插入元素
heapq.heappush(max_heap, -3)
heapq.heappush(max_heap, -1)
heapq.heappush(max_heap, -4)
heapq.heappush(max_heap, -1)
heapq.heappush(max_heap, -5)

# 输出堆顶元素(最大值)
print("Max element in max heap:", -max_heap[0])

# 创建一个小根堆
min_heap = []
# 插入元素
heapq.heappush(min_heap, 3)
heapq.heappush(min_heap, 1)
heapq.heappush(min_heap, 4)
heapq.heappush(min_heap, 1)
heapq.heappush(min_heap, 5)

# 输出堆顶元素(最小值)
print("Min element in min heap:", min_heap[0])

以上是使用代码库实现大根堆和小根堆的示例代码。在 C++ 中,可以使用 std::priority_queue 实现堆,默认情况下为大根堆,也可以自定义比较函数实现小根堆;在 Java 中,可以使用 java.util.PriorityQueue,通过传入比较器实现大根堆或小根堆;在 Python 中,可以使用 heapq 模块,通过调整元素的符号实现大根堆或小根堆。

运行结果

6.集合的操作

集合的定义

集合(Set)是一种不允许重复元素的数据结构,它提供了一种存储和操作不重复元素的方式。在集合中,元素的顺序通常是不确定的,取决于具体的实现。

集合的实现方式

常见的集合实现有两种 :TreeSetHashSetTreeSet 是基于红黑树实现的有序集合,它可以保持元素的排序顺序;HashSet 是基于哈希表实现的无序集合,它具有快速的插入、删除和查找操作。

利用代码库实现TreeSet和HashSet

C++代码实现

TreeSet
cpp 复制代码
#include <iostream>
#include <set>

int main() {
    // 创建一个 TreeSet
    std::set<int> treeSet;

    // 插入元素
    treeSet.insert(10);
    treeSet.insert(5);
    treeSet.insert(20);
    treeSet.insert(15);

    // 遍历输出
    std::cout << "TreeSet elements:";
    for (int num : treeSet) {
        std::cout << " " << num;
    }
    std::cout << std::endl;

    // 删除元素
    treeSet.erase(5);

    // 检查元素是否存在
    if (treeSet.find(20) != treeSet.end()) {
        std::cout << "Element 20 is in the TreeSet." << std::endl;
    }

    return 0;
}
HashSet
cpp 复制代码
#include <iostream>
#include <unordered_set>

int main() {
    // 创建一个 HashSet
    std::unordered_set<int> hashSet;

    // 插入元素
    hashSet.insert(10);
    hashSet.insert(5);
    hashSet.insert(20);
    hashSet.insert(15);

    // 遍历输出
    std::cout << "HashSet elements:";
    for (int num : hashSet) {
        std::cout << " " << num;
    }
    std::cout << std::endl;

    // 删除元素
    hashSet.erase(5);

    // 检查元素是否存在
    if (hashSet.find(20) != hashSet.end()) {
        std::cout << "Element 20 is in the HashSet." << std::endl;
    }

    return 0;
}

Java代码实现

TreeSet
java 复制代码
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        // 创建一个 TreeSet
        TreeSet<Integer> treeSet = new TreeSet<>();

        // 插入元素
        treeSet.add(10);
        treeSet.add(5);
        treeSet.add(20);
        treeSet.add(15);

        // 遍历输出
        System.out.print("TreeSet elements:");
        for (int num : treeSet) {
            System.out.print(" " + num);
        }
        System.out.println();

        // 删除元素
        treeSet.remove(5);

        // 检查元素是否存在
        if (treeSet.contains(20)) {
            System.out.println("Element 20 is in the TreeSet.");
        }
    }
}
HashSet
java 复制代码
import java.util.HashSet;

public class Main {
    public static void main(String[] args) {
        // 创建一个 HashSet
        HashSet<Integer> hashSet = new HashSet<>();

        // 插入元素
        hashSet.add(10);
        hashSet.add(5);
        hashSet.add(20);
        hashSet.add(15);

        // 遍历输出
        System.out.print("HashSet elements:");
        for (int num : hashSet) {
            System.out.print(" " + num);
        }
        System.out.println();

        // 删除元素
        hashSet.remove(5);

        // 检查元素是否存在
        if (hashSet.contains(20)) {
            System.out.println("Element 20 is in the HashSet.");
        }
    }
}

Python代码实现

TreeSet(在 Python 中,通常使用 SortedSet 来模拟 TreeSet 的行为)
python 复制代码
from sortedcontainers import SortedSet

# 创建一个 TreeSet(SortedSet)
treeSet = SortedSet()

# 插入元素
treeSet.add(10)
treeSet.add(5)
treeSet.add(20)
treeSet.add(15)

# 遍历输出
print("TreeSet elements:", end="")
for num in treeSet:
    print(" ", num, end="")
print()

# 删除元素
treeSet.remove(5)

# 检查元素是否存在
if 20 in treeSet:
    print("Element 20 is in the TreeSet.")
HashSet(在 Python 中,通常使用 set 来模拟 HashSet 的行为)
python 复制代码
# 创建一个 HashSet
hashSet = set()

# 插入元素
hashSet.add(10)
hashSet.add(5)
hashSet.add(20)
hashSet.add(15)

# 遍历输出
print("HashSet elements:", end="")
for num in hashSet:
    print(" ", num, end="")
print()

# 删除元素
hashSet.remove(5)

# 检查元素是否存在
if 20 in hashSet:
    print("Element 20 is in the HashSet.")

以上是使用代码库实现 TreeSetHashSet 的示例代码。在 C++ 中,可以使用 std::set 实现 TreeSet,使用 std::unordered_set 实现 HashSet;在 Java 中,可以直接使用 TreeSetHashSet 类;在 Python 中,通常使用 SortedSet(例如 sortedcontainers 库)来模拟 TreeSet,使用 set 来模拟 HashSet。这些代码展示了集合的基本操作,包括插入元素、遍历输出、删除元素和检查元素是否存在等操作。

运行结果

TreeSet
HashSet

7.哈希的操作

Map 是一种键值对映射的数据结构,也被称作哈希表,是用于存储键值对的集合。每个键都唯一且与一个值关联,可以通过键来查找对应的值。

HashMap 的特点

  • 使用哈希表实现,通过哈希函数计算键的存储位置。
  • 元素无序存储,不保证遍历顺序与插入顺序一致。
  • 插入、删除、查找操作的平均时间复杂度为 O(1)。

TreeMap 的特点

  • 使用红黑树实现,元素按照键的自然顺序或者自定义比较器排序。
  • 元素有序存储,可以通过键的顺序进行遍历。
  • 插入、删除、查找操作的时间复杂度为 O(log n)。

代码实现

C++代码实现

HashMap
cpp 复制代码
#include <iostream>
#include <unordered_map>

int main() {
    // 创建一个 HashMap
    std::unordered_map<std::string, int> hashMap;

    // 插入元素
    hashMap["Apple"] = 10;
    hashMap["Banana"] = 20;
    hashMap["Cherry"] = 15;

    // 获取值
    std::cout << "Value for Apple: " << hashMap["Apple"] << std::endl;

    // 遍历
    std::cout << "HashMap elements:" << std::endl;
    for (const auto& pair : hashMap) {
        std::cout << pair.first << " : " << pair.second << std::endl;
    }

    return 0;
}
TreeMap
cpp 复制代码
#include <iostream>
#include <map>

int main() {
    // 创建一个 TreeMap
    std::map<std::string, int> treeMap;

    // 插入元素
    treeMap["Apple"] = 10;
    treeMap["Banana"] = 20;
    treeMap["Cherry"] = 15;

    // 获取值
    std::cout << "Value for Apple: " << treeMap["Apple"] << std::endl;

    // 遍历
    std::cout << "TreeMap elements:" << std::endl;
    for (const auto& pair : treeMap) {
        std::cout << pair.first << " : " << pair.second << std::endl;
    }

    return 0;
}

Java代码实现

HashMap
java 复制代码
import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        // 创建一个 HashMap
        HashMap<String, Integer> hashMap = new HashMap<>();

        // 插入元素
        hashMap.put("Apple", 10);
        hashMap.put("Banana", 20);
        hashMap.put("Cherry", 15);

        // 获取值
        System.out.println("Value for Apple: " + hashMap.get("Apple"));

        // 遍历
        System.out.println("HashMap elements:");
        for (String key : hashMap.keySet()) {
            System.out.println(key + " : " + hashMap.get(key));
        }
    }
}
TreeMap
java 复制代码
import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        // 创建一个 TreeMap
        TreeMap<String, Integer> treeMap = new TreeMap<>();

        // 插入元素
        treeMap.put("Apple", 10);
        treeMap.put("Banana", 20);
        treeMap.put("Cherry", 15);

        // 获取值
        System.out.println("Value for Apple: " + treeMap.get("Apple"));

        // 遍历
        System.out.println("TreeMap elements:");
        for (String key : treeMap.keySet()) {
            System.out.println(key + " : " + treeMap.get(key));
        }
    }
}

Python代码实现

HashMap
python 复制代码
# 创建一个 HashMap
hashMap = {
    "Apple": 10,
    "Banana": 20,
    "Cherry": 15
}

# 获取值
print("Value for Apple:", hashMap["Apple"])

# 遍历
print("HashMap elements:")
for key, value in hashMap.items():
    print(key, ":", value)
TreeMap(Python 没有 TreeMap,用 OrderedDict 模拟)
python 复制代码
from collections import OrderedDict

# 创建一个 TreeMap
treeMap = OrderedDict()

# 插入元素
treeMap["Apple"] = 10
treeMap["Banana"] = 20
treeMap["Cherry"] = 15

# 获取值
print("Value for Apple:", treeMap["Apple"])

# 遍历
print("TreeMap elements:")
for key, value in treeMap.items():
    print(key, ":", value)

运行结果

HashMap
TreeMap

8.树的操作

树(Tree)作为一种重要的数据结构,具有许多常用的操作,包括节点的插入、删除、查找、遍历等。

树的基本操作

下面是树的一些基本操作:

节点的插入

  • 在树中添加一个新节点作为现有节点的子节点。
  • 可以在树的任意位置插入节点,包括作为根节点的子节点或其他节点的子节点。

节点的删除

  • 从树中移除一个指定的节点及其所有子节点。
  • 删除节点时需要考虑其子节点的重新连接,通常有几种情况需要处理。

节点的查找

  • 查找树中是否存在一个特定的节点。
  • 可以根据节点的值或其他属性进行查找。

树的遍历

  • 遍历树是指按照某种顺序访问树中的所有节点。
  • 树的常见遍历方式有:前序遍历、中序遍历、后序遍历和层序遍历。

节点的更新

  • 更新树中某个节点的值或其他属性。

获取树的高度

  • 计算树的高度,即从根节点到最远叶节点的最长路径的长度。

代码实现

C++代码实现

cpp 复制代码
#include <iostream>
#include <vector>

// 树节点结构体
struct TreeNode {
    int val;
    std::vector<TreeNode*> children;  // 存储子节点的邻接表
    TreeNode(int x) : val(x) {}
};

// 插入子节点
void insert(TreeNode* parent, TreeNode* child) {
    parent->children.push_back(child);
}

// 查找节点
TreeNode* search(TreeNode* root, int value) {
    if (root == nullptr || root->val == value) {
        return root;
    }
    for (TreeNode* child : root->children) {
        TreeNode* result = search(child, value);
        if (result != nullptr) {
            return result;
        }
    }
    return nullptr;
}

// 前序遍历
void preOrderTraversal(TreeNode* root) {
    if (root == nullptr) {
        return;
    }
    std::cout << root->val << " ";
    for (TreeNode* child : root->children) {
        preOrderTraversal(child);
    }
}

// 中序遍历
void inOrderTraversal(TreeNode* root) {
    if (root == nullptr) {
        return;
    }
    for (TreeNode* child : root->children) {
        inOrderTraversal(child);
    }
    std::cout << root->val << " ";
}

// 后序遍历
void postOrderTraversal(TreeNode* root) {
    if (root == nullptr) {
        return;
    }
    for (TreeNode* child : root->children) {
        postOrderTraversal(child);
    }
    std::cout << root->val << " ";
}

int main() {
    // 创建根节点 A
    TreeNode* root = new TreeNode(1);

    // 创建子节点 B、C、D
    TreeNode* nodeB = new TreeNode(2);
    TreeNode* nodeC = new TreeNode(3);
    TreeNode* nodeD = new TreeNode(4);

    // 插入子节点
    insert(root, nodeB);
    insert(root, nodeC);
    insert(root, nodeD);

    // 查找节点
    TreeNode* foundNode = search(root, 3);
    if (foundNode != nullptr) {
        std::cout << "Found node: " << foundNode->val << std::endl;
    } else {
        std::cout << "Node not found!" << std::endl;
    }

    // 遍历树
    std::cout << "Preorder traversal: ";
    preOrderTraversal(root);
    std::cout << std::endl;

    std::cout << "Inorder traversal: ";
    inOrderTraversal(root);
    std::cout << std::endl;

    std::cout << "Postorder traversal: ";
    postOrderTraversal(root);
    std::cout << std::endl;

    return 0;
}

Java代码实现

java 复制代码
import java.util.ArrayList;
import java.util.List;

// 树节点类
class TreeNode {
    int val;
    List<TreeNode> children;  // 存储子节点的邻接表

    public TreeNode(int val) {
        this.val = val;
        children = new ArrayList<>();
    }
}

public class TreeOperations {
    // 插入子节点
    public static void insert(TreeNode parent, TreeNode child) {
        parent.children.add(child);
    }

    // 查找节点
    public static TreeNode search(TreeNode root, int value) {
        if (root == null || root.val == value) {
            return root;
        }
        for (TreeNode child : root.children) {
            TreeNode result = search(child, value);
            if (result != null) {
                return result;
            }
        }
        return null;
    }

    // 前序遍历
    public static void preOrderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.print(root.val + " ");
        for (TreeNode child : root.children) {
            preOrderTraversal(child);
        }
    }

    // 中序遍历
    public static void inOrderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        for (TreeNode child : root.children) {
            inOrderTraversal(child);
        }
        System.out.print(root.val + " ");
    }

    // 后序遍历
    public static void postOrderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        for (TreeNode child : root.children) {
            postOrderTraversal(child);
        }
        System.out.print(root.val + " ");
    }

    public static void main(String[] args) {
        // 创建根节点 A
        TreeNode root = new TreeNode(1);

        // 创建子节点 B、C、D
        TreeNode nodeB = new TreeNode(2);
        TreeNode nodeC = new TreeNode(3);
        TreeNode nodeD = new TreeNode(4);

        // 插入子节点
        insert(root, nodeB);
        insert(root, nodeC);
        insert(root, nodeD);

        // 查找节点
        TreeNode foundNode = search(root, 3);
        if (foundNode != null) {
            System.out.println("Found node: " + foundNode.val);
        } else {
            System.out.println("Node not found!");
        }

        // 遍历树
        System.out.print("Preorder traversal: ");
        preOrderTraversal(root);
        System.out.println();

        System.out.print("Inorder traversal: ");
        inOrderTraversal(root);
        System.out.println();

        System.out.print("Postorder traversal: ");
        postOrderTraversal(root);
        System.out.println();
    }
}

Python代码实现

python 复制代码
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.children = []

# 插入子节点
def insert(parent, child):
    parent.children.append(child)

# 查找节点
def search(root, value):
    if root is None or root.val == value:
        return root
    for child in root.children:
        result = search(child, value)
        if result is not None:
            return result
    return None

# 前序遍历
def pre_order_traversal(root):
    if root is None:
        return
    print(root.val, end=" ")
    for child in root.children:
        pre_order_traversal(child)

# 中序遍历
def in_order_traversal(root):
    if root is None:
        return
    for child in root.children:
        in_order_traversal(child)
    print(root.val, end=" ")

# 后序遍历
def post_order_traversal(root):
    if root is None:
        return
    for child in root.children:
        post_order_traversal(child)
    print(root.val, end=" ")

if __name__ == "__main__":
    # 创建根节点 A
    root = TreeNode(1)

    # 创建子节点 B、C、D
    nodeB = TreeNode(2)
    nodeC = TreeNode(3)
    nodeD = TreeNode(4)

    # 插入子节点
    insert(root, nodeB)
    insert(root, nodeC)
    insert(root, nodeD)

    # 查找节点
    found_node = search(root, 3)
    if found_node is not None:
        print("Found node:", found_node.val)
    else:
        print("Node not found!")

    # 遍历树
    print("Preorder traversal:", end=" ")
    pre_order_traversal(root)
    print()

    print("Inorder traversal:", end=" ")
    in_order_traversal(root)
    print()

    print("Postorder traversal:", end=" ")
    post_order_traversal(root)
    print()

这些代码示例展示了树的插入、查找以及前序、中序、后序遍历操作,分别使用了 C++、Java 和 Python 进行实现。

需要注意的是:在二叉树中,中序遍历顺序为左根右,但 N 叉树的的子节点数量可能不同,难以定义左右的概念。在 N 叉树中,一般没有一个标准的定义行为来对中序遍历进行规范,因此实现代码的方式会有很多种,在这里大家可能就会看到后续遍历代码和中序遍历代码很像。而存在 N 叉树前序遍历后续遍历的原因是前序遍历是先访问根,再访问子,后续是先访问子,再访问根。

运行结果

9.图的操作

图的基本操作

图是一种非常重要的数据结构,它可以用来表示各种实际问题中的关系和连接。以下是图常见的操作:

  • 添加边(Add Edge):向图中添加一条边,连接两个顶点。
  • 删除边(Remove Edge):从图中删除一条边,断开两个顶点之间的连接。
  • 获取顶点的邻居(Get Neighbors of a Vertex):获取一个顶点的所有相邻顶点,即与它直接相连的顶点。
  • 检查边的存在(Check Edge Existence):检查图中是否存在一条边,即判断两个顶点之间是否有连接。
  • 遍历图(Traverse the Graph):遍历图中的所有顶点和边,可以使用深度优先搜索(DFS)或广度优先搜索(BFS)等算法进行遍历。
  • 计算图的连通分量(Compute Connected Components):对于无向图,可以计算图中的连通分量,即图中相互连通的子图个数。
  • 检查图的环(Check for Cycles):检查图中是否存在环,即是否存在一个顶点能够回到自己。
  • 计算最短路径(Compute Shortest Path):计算图中两个顶点之间的最短路径,可以使用 Dijkstra 算法或 Floyd-Warshall 算法等。

这些操作使得图可以应用于许多领域,如网络分析、路由算法、社交网络分析等。不同的操作和算法可以根据具体问题选择合适的实现方式,以便更好地解决问题。

邻接矩阵实现图的代码演示

C++代码实现

cpp 复制代码
#include <iostream>
#include <vector>

class Graph {
private:
    int size;
    std::vector<std::vector<int>> matrix;

public:
    Graph(int n) : size(n) {
        matrix.resize(n, std::vector<int>(n, 0));
    }

    // 添加边
    void addEdge(int u, int v) {
        matrix[u][v] = 1;
        matrix[v][u] = 1;
    }

    // 打印图的邻接矩阵
    void printAdjacencyMatrix() {
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j < size; ++j) {
                std::cout << matrix[i][j] << " ";
            }
            std::cout << std::endl;
        }
    }
};

int main() {
    // 创建图
    Graph graph(4);

    // 添加边
    graph.addEdge(0, 1);
    graph.addEdge(0, 2);
    graph.addEdge(1, 3);
    graph.addEdge(2, 3);

    // 打印图的邻接矩阵
    std::cout << "Adjacency Matrix:" << std::endl;
    graph.printAdjacencyMatrix();

    return 0;
}

Java代码实现

java 复制代码
import java.util.Arrays;

public class AdjacencyMatrix {
    private int[][] matrix;
    private int size;

    // 构造函数
    public AdjacencyMatrix(int size) {
        this.size = size;
        this.matrix = new int[size][size];
        for (int[] row : matrix) {
            Arrays.fill(row, 0);
        }
    }

    // 添加边
    public void addEdge(int u, int v) {
        matrix[u][v] = 1;
        matrix[v][u] = 1;
    }

    // 打印图的邻接矩阵
    public void printAdjacencyMatrix() {
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        // 创建图
        AdjacencyMatrix graph = new AdjacencyMatrix(4);

        // 添加边
        graph.addEdge(0, 1);
        graph.addEdge(0, 2);
        graph.addEdge(1, 3);
        graph.addEdge(2, 3);

        // 打印图的邻接矩阵
        System.out.println("Adjacency Matrix:");
        graph.printAdjacencyMatrix();
    }
}

Python代码实现

python 复制代码
class Graph:
    def __init__(self, n):
        self.size = n
        self.matrix = [[0] * n for _ in range(n)]

    # 添加边
    def addEdge(self, u, v):
        self.matrix[u][v] = 1
        self.matrix[v][u] = 1

    # 打印图的邻接矩阵
    def printAdjacencyMatrix(self):
        for row in self.matrix:
            print(" ".join(map(str, row)))

if __name__ == "__main__":
    # 创建图
    graph = Graph(4)

    # 添加边
    graph.addEdge(0, 1)
    graph.addEdge(0, 2)
    graph.addEdge(1, 3)
    graph.addEdge(2, 3)

    # 打印图的邻接矩阵
    print("Adjacency Matrix:")
    graph.printAdjacencyMatrix()

运行结果

邻接表实现图的代码演示

C++代码实现

cpp 复制代码
#include <iostream>
#include <vector>

// 节点结构体
struct Node {
int value;
std::vector<Node*> neighbors;

    Node(int val) : value(val) {}

};

// 图类
class Graph {
private:
std::vector<Node*> nodes;

public:
// 添加节点
void addNode(Node* node) {
nodes.push_back(node);
}

    // 添加边
    void addEdge(Node* u, Node* v) {
        u->neighbors.push_back(v);
        v->neighbors.push_back(u);
    }

    // 打印图的邻接表
    void printAdjacencyList() {
        for (Node* node : nodes) {
            std::cout << "Node " << node->value << " neighbors: ";
            for (Node* neighbor : node->neighbors) {
                std::cout << neighbor->value << " ";
            }
            std::cout << std::endl;
        }
    }

};

int main() {
// 创建节点
Node* node1 = new Node(1);
Node* node2 = new Node(2);
Node* node3 = new Node(3);
Node* node4 = new Node(4);

    // 创建图
    Graph graph;

    // 添加节点到图中
    graph.addNode(node1);
    graph.addNode(node2);
    graph.addNode(node3);
    graph.addNode(node4);

    // 添加边
    graph.addEdge(node1, node2);
    graph.addEdge(node1, node3);
    graph.addEdge(node2, node4);
    graph.addEdge(node3, node4);

    // 打印图的邻接表
    std::cout << "Adjacency List:" << std::endl;
    graph.printAdjacencyList();

    return 0;

}

Java代码实现

java 复制代码
import java.util.ArrayList;
import java.util.List;

// 节点类
class Node {
    int value;
    List<Node> neighbors;

    Node(int val) {
        value = val;
        neighbors = new ArrayList<>();
    }
}

// 图类
class Graph {
    private List<Node> nodes;

    Graph() {
        nodes = new ArrayList<>();
    }

    // 添加节点
    void addNode(Node node) {
        nodes.add(node);
    }

    // 添加边
    void addEdge(Node u, Node v) {
        u.neighbors.add(v);
        v.neighbors.add(u);
    }

    // 打印图的邻接表
    void printAdjacencyList() {
        for (Node node : nodes) {
            System.out.print("Node " + node.value + " neighbors: ");
            for (Node neighbor : node.neighbors) {
                System.out.print(neighbor.value + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        // 创建节点
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);

        // 创建图
        Graph graph = new Graph();

        // 添加节点到图中
        graph.addNode(node1);
        graph.addNode(node2);
        graph.addNode(node3);
        graph.addNode(node4);

        // 添加边
        graph.addEdge(node1, node2);
        graph.addEdge(node1, node3);
        graph.addEdge(node2, node4);
        graph.addEdge(node3, node4);

        // 打印图的邻接表
        System.out.println("Adjacency List:");
        graph.printAdjacencyList();
    }
}

Python代码实现

python 复制代码
# 节点类
class Node:
    def __init__(self, val):
        self.value = val
        self.neighbors = []

# 图类
class Graph:
    def __init__(self):
        self.nodes = []

    # 添加节点
    def addNode(self, node):
        self.nodes.append(node)

    # 添加边
    def addEdge(self, u, v):
        u.neighbors.append(v)
        v.neighbors.append(u)

    # 打印图的邻接表
    def printAdjacencyList(self):
        for node in self.nodes:
            print(f"Node {node.value} neighbors:", end=" ")
            for neighbor in node.neighbors:
                print(neighbor.value, end=" ")
            print()

if __name__ == "__main__":
    # 创建节点
    node1 = Node(1)
    node2 = Node(2)
    node3 = Node(3)
    node4 = Node(4)

    # 创建图
    graph = Graph()

    # 添加节点到图中
    graph.addNode(node1)
    graph.addNode(node2)
    graph.addNode(node3)
    graph.addNode(node4)

    # 添加边
    graph.addEdge(node1, node2)
    graph.addEdge(node1, node3)
    graph.addEdge(node2, node4)
    graph.addEdge(node3, node4)

    # 打印图的邻接表
    print("Adjacency List:")
    graph.printAdjacencyList()

运行结果

相关推荐
Aaron15881 小时前
基于FPGA实现卷积方法比较分析
arm开发·算法·fpga开发·硬件架构·硬件工程·射频工程·基带工程
九千七5261 小时前
sklearn学习(4)K近邻(KNN)
人工智能·学习·机器学习·sklearn·knn·近邻搜索
报错小能手1 小时前
数据结构 循环队列
数据结构
元亓亓亓1 小时前
考研408--数据结构--day4--栈&队列
数据结构·考研··队列
Lyre丶1 小时前
ginan入门初探
linux·经验分享·学习·ubuntu
AndrewHZ1 小时前
【图像处理基石】什么是分水岭算法?
图像处理·算法·计算机视觉·图像分割·cv·形态学分割
前端小L1 小时前
回溯算法专题(五):去重与剪枝的双重奏——攻克「组合总和 II」
算法·剪枝
TL滕1 小时前
从0开始学算法——第三天(数据结构的多样性)
数据结构·笔记·学习·算法
V1ncent Chen1 小时前
人工智能的基石之一:算法
人工智能·算法