算法四 习题 1.3

数组实现栈

#include <iostream>
#include <vector>
#include <stdexcept>
using namespace std;

class MyStack {
private:
    vector<int> data;  // 用于存储栈元素的数组
    
public:
    // 构造函数
    MyStack() {}
    
    // 入栈操作
    void push(int val) {
        data.push_back(val);  // 在数组末尾添加元素
    }
    
    // 出栈操作
    void pop() {
        if (empty()) {
            throw runtime_error("Stack underflow");
        }
        data.pop_back();  // 移除数组末尾元素
    }
    
    // 获取栈顶元素
    int top() {
        if (empty()) {
            throw runtime_error("Stack is empty");
        }
        return data.back();  // 返回数组末尾元素
    }
    
    // 检查栈是否为空
    bool empty() const {
        return data.empty();
    }
    
    // 返回栈中的元素数量
    int size() const {
        return data.size();
    }
};

// 测试程序
int main() {
  
    return 0;
}

链表实现栈

#include <iostream>
#include <stdexcept>
using namespace std;

// 链表节点结构
class Node {
public:
    int data;
    Node* next;
    
    // 构造函数
    Node(int val) : data(val), next(nullptr) {}
};

// 使用链表实现的栈
class LinkedListStack {
private:
    Node* top_ptr;  // 指向栈顶的指针
    int n;          // 栈中元素的数量
    
public:
    // 构造函数
    LinkedListStack() : top_ptr(nullptr), n(0) {}
    
    // 析构函数,释放所有节点
    ~LinkedListStack() {
        while (!empty()) {
            pop();
        }
    }
    
    // 入栈操作
    void push(int val) {
        Node* new_node = new Node(val);
        new_node->next = top_ptr;
        top_ptr = new_node;
        n++;
    }
    
    // 出栈操作
    void pop() {
        if (empty()) {
            throw runtime_error("Stack underflow");
        }
        
        Node* temp = top_ptr;
        top_ptr = top_ptr->next;
        delete temp;
        n--;
    }
    
    // 获取栈顶元素
    int top() {
        if (empty()) {
            throw runtime_error("Stack is empty");
        }
        
        return top_ptr->data;
    }
    
    // 检查栈是否为空
    bool empty() const {
        return top_ptr == nullptr;
    }
    
    // 返回栈中的元素数量
    int size() const {
        return n;
    }
    
    // 打印栈中的所有元素(用于调试)
    void printStack() const {
        if (empty()) {
            cout << "Stack is empty" << endl;
            return;
        }
        
        cout << "Stack (top to bottom): ";
        Node* current = top_ptr;
        while (current != nullptr) {
            cout << current->data << " ";
            current = current->next;
        }
        cout << endl;
    }
};

// 测试程序
int main() {
   
    return 0;
}

双向队列和栈

#include <iostream>
#include <stdexcept>
using namespace std;

// 双向链表节点结构
class Node {
public:
    int data;
    Node* next;
    Node* prev;
    
    // 构造函数
    Node(int val) : data(val), next(nullptr), prev(nullptr) {}
};

// 使用双向链表实现的双向队列
class Deque {
private:
    Node* front;  // 指向队列前端的指针
    Node* back;   // 指向队列后端的指针
    int n;        // 队列中元素的数量
    
public:
    // 构造函数
    Deque() : front(nullptr), back(nullptr), n(0) {}
    
    // 析构函数,释放所有节点
    ~Deque() {
        while (!empty()) {
            removeFront();
        }
    }
    
    // 检查队列是否为空
    bool empty() const {
        return n == 0;
    }
    
    // 返回队列中的元素数量
    int size() const {
        return n;
    }
    
    // 在队列前端添加元素
    void addFront(int val) {
        Node* new_node = new Node(val);
        
        if (empty()) {
            front = back = new_node;
        } else {
            new_node->next = front;
            front->prev = new_node;
            front = new_node;
        }
        
        n++;
    }
    
    // 在队列后端添加元素
    void addBack(int val) {
        Node* new_node = new Node(val);
        
        if (empty()) {
            front = back = new_node;
        } else {
            new_node->prev = back;
            back->next = new_node;
            back = new_node;
        }
        
        n++;
    }
    
    // 从队列前端移除元素
    int removeFront() {
        if (empty()) {
            throw runtime_error("Deque underflow");
        }
        
        Node* temp = front;
        int val = temp->data;
        
        if (front == back) {
            // 队列中只有一个元素
            front = back = nullptr;
        } else {
            front = front->next;
            front->prev = nullptr;
        }
        
        delete temp;
        n--;
        return val;
    }
    
    // 从队列后端移除元素
    int removeBack() {
        if (empty()) {
            throw runtime_error("Deque underflow");
        }
        
        Node* temp = back;
        int val = temp->data;
        
        if (front == back) {
            // 队列中只有一个元素
            front = back = nullptr;
        } else {
            back = back->prev;
            back->next = nullptr;
        }
        
        delete temp;
        n--;
        return val;
    }
    
    // 获取队列前端元素
    int peekFront() const {
        if (empty()) {
            throw runtime_error("Deque is empty");
        }
        
        return front->data;
    }
    
    // 获取队列后端元素
    int peekBack() const {
        if (empty()) {
            throw runtime_error("Deque is empty");
        }
        
        return back->data;
    }
    
    // 打印队列中的所有元素(用于调试)
    void printDeque() const {
        if (empty()) {
            cout << "Deque is empty" << endl;
            return;
        }
        
        cout << "Deque (front to back): ";
        Node* current = front;
        while (current != nullptr) {
            cout << current->data << " ";
            current = current->next;
        }
        cout << endl;
    }
};

// 使用双向队列实现的栈
class DequeStack {
private:
    Deque deque;  // 使用双向队列作为底层数据结构
    
public:
    // 入栈操作(在队列前端添加元素)
    void push(int val) {
        deque.addFront(val);
    }
    
    // 出栈操作(从队列前端移除元素)
    int pop() {
        return deque.removeFront();
    }
    
    // 获取栈顶元素
    int top() const {
        return deque.peekFront();
    }
    
    // 检查栈是否为空
    bool empty() const {
        return deque.empty();
    }
    
    // 返回栈中的元素数量
    int size() const {
        return deque.size();
    }
    
    // 打印栈中的所有元素(用于调试)
    void printStack() const {
        cout << "Stack (via Deque): ";
        deque.printDeque();
    }
};

// 使用双向队列实现的队列
class DequeQueue {
private:
    Deque deque;  // 使用双向队列作为底层数据结构
    
public:
    // 入队操作(在队列后端添加元素)
    void enqueue(int val) {
        deque.addBack(val);
    }
    
    // 出队操作(从队列前端移除元素)
    int dequeue() {
        return deque.removeFront();
    }
    
    // 获取队头元素
    int front() const {
        return deque.peekFront();
    }
    
    // 检查队列是否为空
    bool empty() const {
        return deque.empty();
    }
    
    // 返回队列中的元素数量
    int size() const {
        return deque.size();
    }
    
    // 打印队列中的所有元素(用于调试)
    void printQueue() const {
        cout << "Queue (via Deque): ";
        deque.printDeque();
    }
};

// 测试程序
int main() {
    cout << "===== Testing Deque =====" << endl;
    Deque deque;
    
    deque.addFront(10);
    deque.printDeque();
    deque.addBack(20);
    deque.printDeque();
    deque.addFront(5);
    deque.printDeque();
    deque.addBack(30);
    deque.printDeque();
    
    cout << "Front element: " << deque.peekFront() << endl;
    cout << "Back element: " << deque.peekBack() << endl;
    
    cout << "Removing front: " << deque.removeFront() << endl;
    deque.printDeque();
    cout << "Removing back: " << deque.removeBack() << endl;
    deque.printDeque();
    
    cout << "\n===== Testing Stack implemented with Deque =====" << endl;
    DequeStack stack;
    
    stack.push(10);
    stack.push(20);
    stack.push(30);
    stack.printStack();
    
    cout << "Top element: " << stack.top() << endl;
    cout << "Popping: " << stack.pop() << endl;
    stack.printStack();
    
    cout << "\n===== Testing Queue implemented with Deque =====" << endl;
    DequeQueue queue;
    
    queue.enqueue(10);
    queue.enqueue(20);
    queue.enqueue(30);
    queue.printQueue();
    
    cout << "Front element: " << queue.front() << endl;
    cout << "Dequeuing: " << queue.dequeue() << endl;
    queue.printQueue();
    
    return 0;
}

栈与队列

#include <iostream>
#include <stack>
#include <queue>
#include <stdexcept>
using namespace std;

// 使用两个栈实现队列
class StackQueue {
private:
    stack<int> inbox;   // 用于入队操作的栈
    stack<int> outbox;  // 用于出队操作的栈
    
    // 将元素从inbox转移到outbox
    void transfer() {
        // 只有当outbox为空时才进行转移,保证元素顺序
        if (outbox.empty()) {
            while (!inbox.empty()) {
                outbox.push(inbox.top());
                inbox.pop();
            }
        }
    }
    
public:
    // 入队操作
    void enqueue(int val) {
        inbox.push(val);
    }
    
    // 出队操作
    int dequeue() {
        if (empty()) {
            throw runtime_error("Queue underflow");
        }
        
        transfer();  // 确保outbox不为空
        int val = outbox.top();
        outbox.pop();
        return val;
    }
    
    // 获取队头元素
    int front() {
        if (empty()) {
            throw runtime_error("Queue is empty");
        }
        
        transfer();  // 确保outbox不为空
        return outbox.top();
    }
    
    // 检查队列是否为空
    bool empty() const {
        return inbox.empty() && outbox.empty();
    }
    
    // 返回队列中的元素数量
    int size() const {
        return inbox.size() + outbox.size();
    }
};

// 使用两个队列实现栈
class QueueStack {
private:
    queue<int> q1;  // 主队列,存储所有元素
    queue<int> q2;  // 辅助队列,用于操作
    
public:
    // 入栈操作
    void push(int val) {
        // 将新元素加入主队列
        q1.push(val);
    }
    
    // 出栈操作
    int pop() {
        if (empty()) {
            throw runtime_error("Stack underflow");
        }
        
        // 将q1中除最后一个元素外的所有元素移到q2
        while (q1.size() > 1) {
            q2.push(q1.front());
            q1.pop();
        }
        
        // 保存最后一个元素(栈顶元素)
        int val = q1.front();
        q1.pop();
        
        // 交换q1和q2的角色
        swap(q1, q2);
        
        return val;
    }
    
    // 获取栈顶元素
    int top() {
        if (empty()) {
            throw runtime_error("Stack is empty");
        }
        
        // 将q1中除最后一个元素外的所有元素移到q2
        while (q1.size() > 1) {
            q2.push(q1.front());
            q1.pop();
        }
        
        // 保存最后一个元素(栈顶元素)
        int val = q1.front();
        
        // 将最后一个元素也移到q2
        q2.push(val);
        q1.pop();
        
        // 交换q1和q2的角色
        swap(q1, q2);
        
        return val;
    }
    
    // 检查栈是否为空
    bool empty() const {
        return q1.empty();
    }
    
    // 返回栈中的元素数量
    int size() const {
        return q1.size();
    }
};

// 测试程序
int main() {
    cout << "===== Testing Queue implemented with Stacks =====" << endl;
    StackQueue queue;
    
    cout << "Enqueuing: 10, 20, 30" << endl;
    queue.enqueue(10);
    queue.enqueue(20);
    queue.enqueue(30);
    
    cout << "Queue size: " << queue.size() << endl;
    cout << "Front element: " << queue.front() << endl;
    
    cout << "Dequeuing: " << queue.dequeue() << endl;
    cout << "Front element after dequeue: " << queue.front() << endl;
    cout << "Queue size after dequeue: " << queue.size() << endl;
    
    cout << "Enqueuing: 40" << endl;
    queue.enqueue(40);
    cout << "Queue size: " << queue.size() << endl;
    
    cout << "Emptying queue..." << endl;
    while (!queue.empty()) {
        cout << "Dequeued: " << queue.dequeue() << endl;
    }
    
    cout << "\n===== Testing Stack implemented with Queues =====" << endl;
    QueueStack stack;
    
    cout << "Pushing: 10, 20, 30" << endl;
    stack.push(10);
    stack.push(20);
    stack.push(30);
    
    cout << "Stack size: " << stack.size() << endl;
    cout << "Top element: " << stack.top() << endl;
    
    cout << "Popping: " << stack.pop() << endl;
    cout << "Top element after pop: " << stack.top() << endl;
    cout << "Stack size after pop: " << stack.size() << endl;
    
    cout << "Pushing: 40" << endl;
    stack.push(40);
    cout << "Stack size: " << stack.size() << endl;
    cout << "Top element: " << stack.top() << endl;
    
    cout << "Emptying stack..." << endl;
    while (!stack.empty()) {
        cout << "Popped: " << stack.pop() << endl;
    }
    
    return 0;
}

1.3.9

编写一段程序,从标准输入得到一个缺少左括号的表达式并打印出补全括号之后的中序表达式。例如,给定输入:[需要图示]你的程序应该输出:[需要图示]

#include <iostream>
#include <stack>
#include <string>
using namespace std;

string fixExpression(string& expr) {
    stack<string> operands;
    
    for (char c : expr) {
        if (c == ')') {
            // 遇到右括号,需要添加对应的左括号
            if (!operands.empty()) {
                string top = operands.top();
                operands.pop();
                top = "(" + top + ")";
                
                if (!operands.empty()) {
                    // 将补全的表达式与前面的部分合并
                    string prev = operands.top();
                    operands.pop();
                    operands.push(prev + top);
                } else {
                    operands.push(top);
                }
            }
        } else if (c == '+' || c == '-' || c == '*' || c == '/') {
            // 遇到操作符,将其添加到前一个操作数之后
            if (!operands.empty()) {
                string top = operands.top();
                operands.pop();
                top = top + c;
                operands.push(top);
            }
        } else {
            // 处理操作数(数字或变量)
            string operand(1, c);
            
            if (!operands.empty()) {
                string prev = operands.top();
                operands.pop();
                operands.push(prev + operand);
            } else {
                operands.push(operand);
            }
        }
    }
    
    return operands.empty() ? "" : operands.top();
}

int main() {
    string expression;
    cin >> expression;
    
    cout << fixExpression(expression) << endl;
    
    return 0;
}

1.3.10

编写一个过滤器InfixToPostfix,将算术表达式由中序表达式转为后序表达式。

#include <iostream>
#include <string>
#include <stack>
#include <cctype>

using namespace std;

class InfixToPostfix {
public:
    // 获取操作符的优先级
    int getPrecedence(char op) {
        if (op == '+' || op == '-')
            return 1;
        if (op == '*' || op == '/')
            return 2;
        return 0;  // 括号的优先级最低
    }
    
    // 中序表达式转后序表达式的主函数
    string convert(const string& infix) {
        string postfix = "";
        stack<char> operatorStack;
        
        for (int i = 0; i < infix.length(); i++) {
            char c = infix[i];
            
            // 如果是空格,跳过
            if (c == ' ')
                continue;
            
            // 如果是操作数(数字或字母),直接添加到结果中
            if (isalnum(c)) {
                postfix += c;
            }
            // 如果是左括号,入栈
            else if (c == '(') {
                operatorStack.push(c);
            }
            // 如果是右括号,弹出栈中元素直到遇到左括号
            else if (c == ')') {
                while (!operatorStack.empty() && operatorStack.top() != '(') {
                    postfix += operatorStack.top();
                    operatorStack.pop();
                }
                
                // 弹出左括号
                if (!operatorStack.empty() && operatorStack.top() == '(') {
                    operatorStack.pop();
                }
            }
            // 如果是运算符
            else {
                // 弹出优先级大于或等于当前运算符的所有运算符
                while (!operatorStack.empty() && operatorStack.top() != '(' && 
                       getPrecedence(operatorStack.top()) >= getPrecedence(c)) {
                    postfix += operatorStack.top();
                    operatorStack.pop();
                }
                // 当前运算符入栈
                operatorStack.push(c);
            }
        }
        
        // 处理栈中剩余的运算符
        while (!operatorStack.empty()) {
            if (operatorStack.top() != '(') {
                postfix += operatorStack.top();
            }
            operatorStack.pop();
        }
        
        return postfix;
    }
};

int main() {
    InfixToPostfix converter;
    string infix;
    
    cout << "请输入中序表达式: ";
    getline(cin, infix);
    
    string postfix = converter.convert(infix);
    cout << "后序表达式: " << postfix << endl;
    
    return 0;
}

1.3.11

编写一段程序EvaluatePostfix,从标准输入中得到一个后序表达式,求值并打印结果(将上一题的程序中得到的输出用管道传递给这一段程序可以得到和Evaluate相同的行为)。

const int maxn = 1e4 + 50;
int st[maxn],idx;
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        idx = -1;
        for(const auto& t : tokens){
            if(t != "+" and t != "-" and t != "*" and t != "/"){
                st[++idx] = stoi(t);
            }else{
                auto a = st[idx--];
                auto b = st[idx--];
                if(t == "+") st[++idx] = b + a;
                else if(t == "-") st[++idx] = b - a;
                else if(t == "*") st[++idx] = b * a;
                else st[++idx] = b / a;
            }
        }
        return st[idx];
    }
};

1.3.12

编写一个可迭代的Stack用例,它含有一个静态的copy()方法,接受一个字符串的栈作为参数并返回该栈的一个副本。注意:这种能力是迭代器价值的一个重要体现,因为有了它我们无需改变基本API就能够实现这种功能。

1.3.14

编写一个类ResizingArrayQueueOfStrings,使用定长数组实现队列的抽象,然后扩展实现,使用调整数组的方法突破大小的限制。

1.3.15

编写一个Queue的用例,接受一个命令行参数k并打印出标准输入中的倒数第k个字符串(假设标准输入中至少有k个字符串)。

#include <iostream>
#include <string>
#include <deque>
#include <stdexcept>

int main(int argc, char* argv[]) {
    // 检查命令行参数
    if (argc != 2) {
        std::cerr << "用法: " << argv[0] << " k" << std::endl;
        return 1;
    }
    
    // 解析参数k
    int k;
    try {
        k = std::stoi(argv[1]);
        if (k <= 0) {
            throw std::invalid_argument("k必须是正整数");
        }
    } catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << std::endl;
        return 1;
    }
    
    // 使用deque作为循环缓冲区
    std::deque<std::string> buffer;
    std::string line;
    
    // 从标准输入读取字符串
    while (std::getline(std::cin, line)) {
        if (!line.empty()) {
            // 将字符串加入缓冲区
            buffer.push_back(line);
            
            // 如果缓冲区大小超过k,移除最早的元素
            if (buffer.size() > k) {
                buffer.pop_front();
            }
        }
    }
    
    // 检查输入是否至少有k个字符串
    if (buffer.size() < k) {
        std::cerr << "错误:输入中的字符串数量少于" << k << "个" << std::endl;
        return 1;
    }
    
    // 打印倒数第k个字符串
    // 在含有k个元素的缓冲区中,最前面的元素就是倒数第k个
    std::cout << buffer.front() << std::endl;
    
    return 0;
}

链表练习

struct Node{
	String item;
	int val;
	Node* next;
	Node(string s, Node* nxt = nullptr) : item(s), val(0), next(nxt) {} Node(int v, Node* nxt = nullptr) : item(""), val(v), next(nxt) {}
};

1.3.19

给出一段代码,删除链表的尾结点,其中链表的首结点为first。

void removeTail(Node* first){
	Node* cur = first;
	if(first == nullptr || first->next ==nullptr){
		delete first;
		first = nullptr;
		return;
	}
	while(cur->next->next!=nullptr){
		cur = cur->next;
	}
	delete cur->next;
	cur->next = nullptr;
}

1.3.20

编写一个方法delete(),接受一个int参数k,删除链表的第k个元素(如果它存在的话)。


void delete(int k,Node* first){
	if(first ==nullptr) return;

	if(k==1){
		Node *tmp = first;
		first = first->next;
		delete tmp;
		return;
	}
	// 寻找第k-1个结点
	Node* cur = first;
	int i = 1;
	while(i<k-1&&cur!=nullptr){
		cur = cur->next;
		i++;
	}
	
	// 如果找不到第k个节点说明链表比k短
	if(cur==nullptr||cur->next == nullptr) return;
	
	Node* tmp = cur->next;
	cur->next = tmp->next;
	delete tmp;
}

1.3.21

编写一个方法find(),接受一条链表和一个字符串key作为参数。如果链表中的某个结点的item域的值为key,则方法返回true,否则返回false。

bool find(Node* first, const string& key) {
    Node* cur = first;
    while (cur != nullptr) {
        if (cur->item == key) {
            return true;
        }
        cur = cur->next;
    }
    return false;
}

1.3.24

编写一个方法 removeAfter(),接受一个链表结点作为参数并删除该结点的后续结点(如果参数结点或参数结点的后续结点为空则什么也不做)。

void removeAfter(Node* node) {
    // 如果结点为空或结点的后续结点为空,什么也不做
    if (node == nullptr || node->next == nullptr) return;
    
    // 保存后续结点的引用
    Node* toDelete = node->next;
    
    // 更新链接,跳过后续结点
    node->next = toDelete->next;
    
    // 删除后续结点
    delete toDelete;
}

1.3.25

编写一个方法 insertAfter(),接受两个链表结点作为参数,将第二个结点插入链表并使之成为第一个结点的后续结点(如果两个参数为空则什么也不做)。

void insertAfter(Node* first, Node* second) {
    // 如果任一结点为空,什么也不做
    if (first == nullptr || second == nullptr) return;
    
    // 将second插入到first之后
    second->next = first->next;
    first->next = second;
}

1.3.26

编写一个方法 remove(),接受一条链表和一个字符串 key 作为参数,删除链表中所有 item 域为 key 的结点。

void remove(Node* head,const string& key){
	if(head!=nullptr&&head->item==key){{
		Node* toDelete = head;
		head = toDelete->next;
		delete toDelete;
	}
	if(head==nullptr) return;

	Node* cur = head;
	while(cur->next!=nullptr){
		if(cur->next->item==key){
			Node* tmp = cur->next;
			cur->next = tmp->next;
			delete tmp;
			// cur = cur->next;  
		}else {
			cur = cur->next;
		}
	}
}
void remove(Node* &head, const string& key) {
    // 处理头部节点
    while (head != nullptr && head->item == key) {
        Node* toDelete = head;
        head = head->next;
        delete toDelete;
    }
    
    // 如果链表变为空
    if (head == nullptr) return;
    
    // 处理剩余节点
    Node* cur = head;
    while (cur->next != nullptr) {
        if (cur->next->item == key) {
            Node* toDelete = cur->next;
            cur->next = toDelete->next;
            delete toDelete;
            // 注意这里不移动cur,因为cur->next已经变成了新的节点
        } else {
            cur = cur->next;
        }
    }
}

1.3.27

编写一个方法 max(),接受一条链表的首结点作为参数,返回链表中最大的节点的值。假设所有链接均为正整数,如果链表为空则返回0。

// 1.3.27 返回链表中最大的节点值(假设为整数)
int max(Node* first) {
    // 如果链表为空,返回0
    if (first == nullptr) return 0;
    
    int maxVal = first->val;
    Node* cur = first->next;
    
    while (cur != nullptr) {
        if (cur->val > maxVal) {
            maxVal = cur->val;
        }
        cur = cur->next;
    }
    
    return maxVal;
}

1.3.28

用递归解答上一题。

int max(Node* first) {
    // 基本情况:如果链表为空,返回0
    if (first == nullptr) return 0;
    
    // 递归计算剩余链表中的最大值
    int restMax = max(first->next);
    
    // 返回当前节点值和剩余最大值中的较大者
    return (first->val > restMax) ? first->val : restMax;
}

1.3.29

用环形链表实现 Queue。环形链表也是一条链表,只是没有任何结点的链接为空,且只需链接非空则 last.next 的值为 first。只能使用一个 Node 类型的实例变量(last)。

struct Node{
	string item; // 节点存储的数据 
	Node* next; // 指向下一个节点的指针 
	// 构造函数 
	Node(const string& data) : item(data), next(nullptr) {}
}

class MyQueue{
	Node* last;
	int n;
public:
	CircularQueue() : last(nullptr), n(0) {}
	 // 检查队列是否为空
    bool isEmpty() const {
        return last == nullptr;
    }
    
    // 返回队列中的元素数量
    int size() const {
        return n;
    }
    
    // 入队操作(在队尾添加元素)
    void enqueue(const string& item) {
        Node* newNode = new Node(item);
        
        if (isEmpty()) {
            // 如果队列为空,创建一个只有一个节点的环
            newNode->next = newNode;
            last = newNode;
        } else {
            // 将新节点插入到环中,成为新的last->next之后的节点
            newNode->next = last->next;
            last->next = newNode;
            // 更新last指向新节点
            last = newNode;
        }
        
        n++;
    }
    
    // 出队操作(从队头移除元素)
    string dequeue() {
        if (isEmpty()) {
            throw runtime_error("Queue underflow");
        }
        
        // 获取队头元素(last->next)
        Node* first = last->next;
        string item = first->item;
        
        if (first == last) {
            // 如果队列中只有一个元素
            delete first;
            last = nullptr;
        } else {
            // 从环中移除队头元素
            last->next = first->next;
            delete first;
        }
        
        n--;
        return item;
    }
    
    // 获取队头元素(不移除)
    string peek() const {
        if (isEmpty()) {
            throw runtime_error("Queue underflow");
        }
        
        return last->next->item;
    }
}

1.3.31

在两个有序链表中的三个变量的作用:reverse、first 和 second。在递归实现中,我们从原链表中提取结点 first 并将它插入到逆链表的开头。我们需要一直保持 first 指向原链表中所有剩余结点的首结点,second 指向原链表中所有剩余结点的第二个结点。

提取的题目还包括两个关于链表反转的实现:

  1. 使用迭代方法实现链表反转函数 reverse()
  2. 使用递归方法实现链表反转函数 reverse()
#include <iostream>
using namespace std;

// 单向链表节点结构
class Node {
public:
    int data;
    Node* next;
    
    // 构造函数
    Node(int val) : data(val), next(nullptr) {}
};

// 打印链表(用于测试)
void printList(Node* head) {
    Node* current = head;
    while (current != nullptr) {
        cout << current->data << " -> ";
        current = current->next;
    }
    cout << "nullptr" << endl;
}

// 创建测试链表
Node* createTestList() {
    Node* head = new Node(1);
    head->next = new Node(2);
    head->next->next = new Node(3);
    head->next->next->next = new Node(4);
    head->next->next->next->next = new Node(5);
    return head;
}

// 释放链表内存
void freeList(Node* head) {
    while (head != nullptr) {
        Node* temp = head;
        head = head->next;
        delete temp;
    }
}

// 使用迭代方法实现链表反转
Node* reverseIterative(Node* head) {
    Node* reverse = nullptr;  // 反转后的链表头
    Node* first = head;       // 指向原链表中所有剩余结点的首结点
    
    while (first != nullptr) {
        Node* second = first->next;  // 指向原链表中所有剩余结点的第二个结点
        
        // 将 first 插入到反转链表的开头
        first->next = reverse;
        reverse = first;
        
        // 移动到下一个节点
        first = second;
    }
    
    return reverse;
}

// 使用递归方法实现链表反转
Node* reverseRecursive(Node* head) {
    // 基本情况:空链表或只有一个节点
    if (head == nullptr || head->next == nullptr) {
        return head;
    }
    
    // first 指向原链表的第一个节点
    Node* first = head;
    // second 指向原链表的第二个节点
    Node* second = first->next;
    
    // 递归反转剩余的链表(从第二个节点开始)
    Node* rest = reverseRecursive(second);
    
    // 将第一个节点连接到反转后链表的末尾
    second->next = first;
    first->next = nullptr;
    
    return rest;
}

// 另一种递归实现(更接近题目描述)
Node* reverseRecursiveAlt(Node* first) {
    // 基本情况:空链表
    if (first == nullptr) return nullptr;
    
    // 基本情况:只有一个节点
    if (first->next == nullptr) return first;
    
    // second 指向原链表的第二个节点
    Node* second = first->next;
    // 递归反转剩余的链表(从第二个节点开始)
    Node* rest = reverseRecursiveAlt(second);
    
    // 将第二个节点指向第一个节点
    second->next = first;
    // 将第一个节点指向 nullptr(它将成为新链表的最后一个节点)
    first->next = nullptr;
    
    return rest;
}

int main() {
    // 测试迭代方法
    
    return 0;
}

1.3.32

实现一个泛型类 DoubleNode 用来构造双向链表,其中每个结点都含有一个指向前面元素的引用和一项指向后面元素的引用(如果不存在则为 null)。为以下任务实现若干静态方法:在表头插入结点、在表尾插入结点、从表头删除结点、从表尾删除结点、在指定结点之前插入新结点、在指定结点之后插入新结点、删除指定结点。

#include <iostream>
#include <stdexcept>
using namespace std;

// 泛型双向链表节点类
template <typename T>
class DoubleNode {
public:
    T data;
    DoubleNode<T>* prev;
    DoubleNode<T>* next;
    
    // 构造函数
    DoubleNode(T val) : data(val), prev(nullptr), next(nullptr) {}
};

// 双向链表操作的静态方法类
template <typename T>
class DoublyLinkedList {
public:
    // 在表头插入结点
    static DoubleNode<T>* insertAtHead(DoubleNode<T>* head, T val) {
        DoubleNode<T>* newNode = new DoubleNode<T>(val);
        
        if (head == nullptr) {
            return newNode;
        }
        
        newNode->next = head;
        head->prev = newNode;
        return newNode;
    }
    
    // 在表尾插入结点
    static DoubleNode<T>* insertAtTail(DoubleNode<T>* head, T val) {
        DoubleNode<T>* newNode = new DoubleNode<T>(val);
        
        if (head == nullptr) {
            return newNode;
        }
        
        // 找到链表的尾结点
        DoubleNode<T>* current = head;
        while (current->next != nullptr) {
            current = current->next;
        }
        
        current->next = newNode;
        newNode->prev = current;
        return head;
    }
    
    // 从表头删除结点
    static DoubleNode<T>* removeFromHead(DoubleNode<T>* head) {
        if (head == nullptr) {
            throw runtime_error("Cannot remove from empty list");
        }
        
        DoubleNode<T>* newHead = head->next;
        if (newHead != nullptr) {
            newHead->prev = nullptr;
        }
        
        delete head;
        return newHead;
    }
    
    // 从表尾删除结点
    static DoubleNode<T>* removeFromTail(DoubleNode<T>* head) {
        if (head == nullptr) {
            throw runtime_error("Cannot remove from empty list");
        }
        
        // 如果只有一个节点
        if (head->next == nullptr) {
            delete head;
            return nullptr;
        }
        
        // 找到尾结点和倒数第二个结点
        DoubleNode<T>* current = head;
        while (current->next != nullptr) {
            current = current->next;
        }
        
        // 删除尾结点
        DoubleNode<T>* newTail = current->prev;
        newTail->next = nullptr;
        delete current;
        
        return head;
    }
    
    // 在指定结点之前插入新结点
    static DoubleNode<T>* insertBefore(DoubleNode<T>* head, DoubleNode<T>* node, T val) {
        if (head == nullptr || node == nullptr) {
            throw runtime_error("Invalid operation");
        }
        
        // 如果在头结点之前插入
        if (node == head) {
            return insertAtHead(head, val);
        }
        
        DoubleNode<T>* newNode = new DoubleNode<T>(val);
        DoubleNode<T>* prevNode = node->prev;
        
        newNode->next = node;
        newNode->prev = prevNode;
        node->prev = newNode;
        prevNode->next = newNode;
        
        return head;
    }
    
    // 在指定结点之后插入新结点
    static DoubleNode<T>* insertAfter(DoubleNode<T>* head, DoubleNode<T>* node, T val) {
        if (head == nullptr || node == nullptr) {
            throw runtime_error("Invalid operation");
        }
        
        DoubleNode<T>* newNode = new DoubleNode<T>(val);
        DoubleNode<T>* nextNode = node->next;
        
        newNode->prev = node;
        newNode->next = nextNode;
        node->next = newNode;
        
        if (nextNode != nullptr) {
            nextNode->prev = newNode;
        }
        
        return head;
    }
    
    // 删除指定结点
    static DoubleNode<T>* remove(DoubleNode<T>* head, DoubleNode<T>* node) {
        if (head == nullptr || node == nullptr) {
            throw runtime_error("Invalid operation");
        }
        
        // 如果删除的是头结点
        if (node == head) {
            return removeFromHead(head);
        }
        
        DoubleNode<T>* prevNode = node->prev;
        DoubleNode<T>* nextNode = node->next;
        
        prevNode->next = nextNode;
        if (nextNode != nullptr) {
            nextNode->prev = prevNode;
        }
        
        delete node;
        return head;
    }
    
    // 查找指定值的节点
    static DoubleNode<T>* find(DoubleNode<T>* head, T val) {
        DoubleNode<T>* current = head;
        while (current != nullptr) {
            if (current->data == val) {
                return current;
            }
            current = current->next;
        }
        return nullptr;
    }
    
    // 打印链表(用于测试)
    static void printList(DoubleNode<T>* head) {
        cout << "Forward: nullptr <-> ";
        DoubleNode<T>* current = head;
        while (current != nullptr) {
            cout << current->data << " <-> ";
            current = current->next;
        }
        cout << "nullptr" << endl;
        
        // 从尾到头打印链表(验证prev指针)
        cout << "Backward: nullptr <-> ";
        if (head != nullptr) {
            // 找到尾结点
            current = head;
            while (current->next != nullptr) {
                current = current->next;
            }
            
            // 从尾到头打印
            while (current != nullptr) {
                cout << current->data << " <-> ";
                current = current->prev;
            }
        }
        cout << "nullptr" << endl;
    }
    
    // 释放链表内存
    static void freeList(DoubleNode<T>* head) {
        while (head != nullptr) {
            DoubleNode<T>* temp = head;
            head = head->next;
            delete temp;
        }
    }
};

// 测试程序
int main() {
    DoubleNode<int>* list = nullptr;
    
    return 0;
}

lc

138 随机链表的复制

25 k个一组反转链表

实现最小栈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值