顺序栈

//Stack.h
template<typename T,int Size=10>
class Stack
{
public:
    Stack();
    ~Stack();
    void push(const T &);
    void pop();
    T & top();
    bool empty();
    bool full();
private:
    T _arr[Size];
    int _top;
};
//Stack.cc
template<typename T,int Size>
Stack<T,Size>::Stack()
:_top(-1)
,_arr(new T[Size])
{}

template<typename T,int Size>
Stack<T,Size>::~Stack()
{
    delete [] _arr;
}

template<typename T,int Size>
void Stack<T,Size>::push(const T & elem)
{
    if(full())
    {
        cout << "full stack" << endl;
        return;
    }
    _arr[++_top] = elem;
}

template<typename T,int Size>
void Stack<T,Size>::pop()
{
    if(empty())
    {
        cout << "empty stack" << endl;
        return;
    }
    --_top;
}

template<typename T,int Size>
T & Stack<T,Size>::top()
{
    return _arr[_top];
}

template<typename T,int Size>
bool Stack<T,Size>::empty()
{
    return _top == -1;
}

template<typename T,int Size>
bool Stack<T,Size>::full()
{
    return _top == Size-1;
}

链栈

//Stack.h
template<typename T>
typedef struct StackNode
{
    T data;
    struct StackNode * next;
}StackNode, *LinkStackPtr;

template<typename T>
class Stack
{
public:
    Stack();
    void push(const T &);
    void pop();
    T & top();
    bool empty();
private:
    LinkStackPtr _top;
    int _length;
};
//Stack.cc
template<typename T>
Stack<T>::Stack()
:_length(0),
:_top(NULL)
{}

template<typename T>
void Stack<T>::push(const T & data)
{
    LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
    q->data= data;
    q->next = _top;
    _top = q;
    ++_length;
}

template<typename T>
void Stack<T>::pop()
{
    if(empty())
    {
        cout << "empty stack" << endl;
        return;
    }
    LinkStackPtr p = _top;
    _top = p->next;
    free(_top);
    --_length;
}

template<typename T>
T & Stack<T>::top()
{
    return _top->data;
}

template<typename T>
bool Stack<T>::empty()
{
    return _length == 0;
}

两栈共享空间

栈的应用:括号匹配,表达式求值,递归,进制转换,迷宫求解

<think>我们正在讨论数据结构中关于的操作,特别是清空的方法和实现。根据之前的引用内容,清空通常是将顶指针重置到初始状态(如-1),而不是释放的存储空间。销毁则是释放所占用的内存资源。 根据引用[1]中的清空操作: ```c /* 清空 */ bool ClearStack(SqStack &S) { if (S.top == -1) return false; S.top = -1; // 将顶指针指向-1,遍历的时候到top就结束 return true; } ``` 这里,清空的操作非常简单,直接将顶指针top置为-1(初始状态)即可。这样中原来的数据虽然没有被覆盖,但因为顶指针已经指向了初始位置,后续的操作会覆盖原来的数据,因此逻辑上已经被清空。 引用[3]中也提到了初始化时是将顶指针置为-1,并且将数组中元素置0(可选操作)。清空的操作与初始化类似,但通常不需要将数组中的每个元素都重置(除非有特殊的安全要求),因为只需要重置顶指针,在逻辑上就为空了。 另外,注意清空和销毁的区别: - 清空(ClearStack):重置的状态,使其成为空,但的存储空间仍然保留,可以继续使用。 - 销毁(DestroyStack):释放所占用的内存资源,不再存在。引用[1]中销毁的操作为: ```c /* 销毁 */ bool DestroyStack(SqStack &S) { if (S.top == -1) return false; free(S.data); // 释放的存储空间 return true; } ``` 注意:销毁的操作中释放了的存储数组(S.data),并将顶指针置为-1(在引用[1]的销毁操作中没有重置top,但通常销毁后结构本身可能也不再使用,所以重置top不是必须的,但释放内存是必须的)。另外,如果结构本身是动态分配的(如引用[1]中的是静态数组,但如果是动态分配的整个结构体,则销毁时需要释放整个结构体),则销毁方式会有所不同。 下面我将详细介绍清空的方法和实现,包括顺序(静态分配和动态分配)和链式。 ## 一、顺序的清空操作 ### 1. 静态分配的顺序 静态分配的顺序使用固定大小的数组存储元素,清空操作只需重置顶指针。 ```c // 结构定义 #define MAXSIZE 100 // 的最大容量 typedef struct { int data[MAXSIZE]; // 静态数组 int top; // 顶指针,初始为-1 } SqStack; // 清空 void ClearStack(SqStack *S) { S->top = -1; // 重置顶指针 } ``` ### 2. 动态分配的顺序 动态分配的顺序在初始化时动态分配了存储数组,清空操作同样只需重置顶指针,不需要释放数组内存(因为清空后还要继续使用)。 ```c // 动态分配的顺序结构 typedef struct { int *data; // 动态数组 int top; // 顶指针 int capacity; // 的容量 } DynStack; // 清空 void ClearStack(DynStack *S) { S->top = -1; // 重置顶指针 // 注意:动态数组的内存不释放,因为还要继续使用 } ``` ## 二、链式的清空操作 链式使用链表存储元素,清空操作需要释放所有节点的内存,并将顶指针置为NULL。 ```c // 链式节点 typedef struct StackNode { int data; struct StackNode *next; } StackNode; // 链式结构 typedef struct { StackNode *top; // 顶指针 } LinkStack; // 清空(需要释放所有节点) void ClearStack(LinkStack *S) { StackNode *p = S->top; while (p) { StackNode *temp = p; p = p->next; free(temp); // 释放节点 } S->top = NULL; // 顶指针置空 } ``` ## 三、注意事项 1. **清空与销毁的区别**: - 清空:重置为空状态,保留存储空间。 - 销毁:释放所有资源,不再存在。 2. **时间复杂度**: - 顺序清空:$O(1)$(只需重置指针) - 链式清空:$O(n)$(需要遍历释放所有节点) 3. **安全考虑**: - 在清空链式时,要防止内存泄漏,必须释放所有节点。 - 顺序清空后,原来的数据可能残留在数组中,如果涉及敏感数据,应该手动覆盖(但通常清空操作只重置指针)。 ## 四、清空操作示例 以下是一个完整的顺序(静态分配)清空操作的示例代码: ```c #include <stdio.h> #include <stdbool.h> #define MAXSIZE 10 typedef struct { int data[MAXSIZE]; int top; } SqStack; // 初始化 void InitStack(SqStack *S) { S->top = -1; } // 清空 void ClearStack(SqStack *S) { S->top = -1; } // 判断空 bool StackEmpty(SqStack S) { return S.top == -1; } int main() { SqStack S; InitStack(&S); // ... 入操作 ... // 清空 ClearStack(&S); if (StackEmpty(S)) { printf("已清空\n"); // 输出:已清空 } return 0; } ``` ## 五、引用说明 - 清空顺序只需重置顶指针(静态和动态分配)[^1][^3]。 - 链式的清空需要逐个释放节点并将顶指针置空。 §§相关问题§§ 1. 的清空操作和销毁操作在哪些场景下需要分别使用? 2. 链式的清空操作中如何避免内存泄漏? 3. 如何实现一个支持撤销操作(使用多个)的编辑器? 4. 在递归函数调用中如何保存现场? 5. 顺序和链式在清空操作上的性能差异对实际应用有什么影响? </think>## 数据结构中清空的方法与实现详解 ### 一、清空的核心概念 清空(Clear Stack)是指**重置的状态使其成为逻辑空**,但不释放的存储空间。这与销毁(Destroy Stack)有本质区别: - 清空:保留数据结构,仅移除所有元素(时间复杂度$O(1)$) - 销毁:释放占用的内存资源(时间复杂度$O(1)$或$O(n)$)[^1][^3] ### 二、顺序的清空实现 #### 1. 静态分配的顺序 ```c /* 清空静态顺序 */ bool ClearStack(SqStack *S) { if (S->top == -1) return false; // 已是空 S->top = -1; // 核心操作:重置顶指针 return true; } ``` - **操作原理**:顶指针`top`置为初始值-1,标记为空状态 - **时间复杂度**:$O(1)$ - **空间复杂度**:$O(1)$ - **特点**:原数据未被覆盖但逻辑失效[^1] #### 2. 动态分配的顺序 ```c /* 清空动态顺序 */ bool ClearStack_Dynamic(DynStack *S) { if (S->top == -1) return false; S->top = -1; // 重置顶指针 // S->data数组保留不释放 return true; } ``` - **关键区别**:保留动态分配的存储数组,仅重置指针[^3] ### 三、链式的清空实现 ```c /* 清空链式 */ void ClearStack_Linked(LinkStack *S) { while (S->top != NULL) { // 遍历释放所有节点 StackNode *temp = S->top; S->top = S->top->next; free(temp); // 释放节点内存 } S->count = 0; // 重置节点计数器 } ``` - **时间复杂度**:$O(n)$(需遍历所有节点) - **空间复杂度**:$O(1)$ - **特点**:必须显式释放每个节点内存[^3] ### 四、清空操作的技术要点 1. **状态重置**: - 顺序:`top = -1` - 链式:`top = NULL` + `count = 0` 2. **内存处理差异**: ```mermaid graph LR A[清空操作] --> B[顺序] A --> C[链式] B --> D[仅重置指针] C --> E[释放所有节点] ``` 3. **错误处理**: - 检查是否已空(避免冗余操作) - 检查指针有效性(防野指针) ### 五、清空 vs 销毁 vs 初始化 | 操作 | 目标 | 内存变化 | 状态 | |--------|-----------------------|--------------------|--------------| | 清空 | 移除所有元素 | 存储空间保留 | 逻辑空 | | 销毁 | 释放所有资源 | 内存完全释放 | 不存在 | | 初始化 | 创建空结构 | 分配/重置内存 | 初始空 | > **应用场景**:清空操作常用于需要复用结构的场景,如编译器语法分析中的符号重用[^1] ### 六、完整示例(顺序清空) ```c #include <stdio.h> #define MAXSIZE 100 typedef struct { int data[MAXSIZE]; int top; } SqStack; // 初始化 void InitStack(SqStack *S) { S->top = -1; // 初始空标记[^3] } // 清空 void ClearStack(SqStack *S) { S->top = -1; // 核心清空操作 } // 检测int IsEmpty(SqStack S) { return (S.top == -1); } int main() { SqStack S; InitStack(&S); // ... 入操作 ... ClearStack(&S); printf("是否空: %d\n", IsEmpty(S)); // 输出1(真) return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值