栈是一种先入先出逻辑的线性结构。通常情况下,我们可以直接使用编程语言内置的栈类。然而,某些语言可能没有专门提供栈类,这时我们可以将该语言的“数组”或“链表”当作栈来使用,并在程序逻辑上忽略与栈无关的操作。
1. 栈的常用操作
push()\pop()\peek()\top()\size()\empty()
2.栈的实现
栈的实现有两种方式,一种是基于链表的实现,一种基于数组的实现。
i:基于链表的实现
此时,链表的头节点是作为栈顶,链表的尾节点作为栈底。
对于入栈操作,只需要将元素插入链表头部,这种节点插入方法被称为“头插法”。对于出栈可以将头节点从链表中删除。
//基于链表实现的栈
class LinkedListStack{
private:
ListNode* stackTop;//将头节点作为栈顶
int stkSize;//栈的长度
public:
ListedListStack(){
stackTop = nullptr;
stkSize=0;
}
~ListedListStack(){
//遍历链表删除节点,释放内存
freeMemoryLinkedList(stackTop);
}
//获取栈的长度
int size(){
return stkSize;
}
//判断栈是否为空
bool isEmpty(){
return size()==0;
}
//访问栈顶元素
int top(){
if(isEmpty()) throw out_of_range("栈为空");
return stackTop->val;
}
//入栈操作
void push(int num){
ListNode* node=new ListNode(num);
node->next=stackTop;
stackTop=node;//更新栈顶
stkSize++;//更新栈中的元素个数
}
//出栈操作
int pop(){
int num =top();
ListNode* tmp=stackTop;
stackTop=stackTop->next;
//释放内存
delete tmp;
stkSize--;
return num;
}
//将List转化为Array并非返回
vector<int> toVector(){
ListNode* node = stackTop;
vector<int> res(size());
for(int i = res.size()-1;i>=0;i--){
res[i]=node->val;//从栈顶元素开始一一复制到数组中去
node=node->next;
}
return res;
}
};
ii:基于数组的实现
将数组的尾部作为栈顶。入栈和出栈分别对应数组尾部的添加和删除元素。时间复杂度为O(1)。由于栈可能会不断的增加,可以使用动态数组实现,这样就不用自己处理数组的扩容问题。
//基于数组实现的栈
class ArrayStack{
private:
vector<int> stack;//动态数组实现
public:
//获取栈的长度
int size(){
return stack.size();
}
//判断栈是否为空
bool isEmpty(){
return stack.size()==0;
}
//入栈操作
void push(int num){
stack.push_back(num);
}
//访问栈顶
int top(){
if(isEmpty()) throw out_of_range(" 栈为空");
return stack.back();
}
//出栈操作,一般涉及到出栈都会返回,出的是什么元素(有返回值)
int pop(){
int num=top();//保存用于出栈的返回值
stack.pop_back();
return num;
}
//返回Vector
vector<int> toVector(){
return stack;
}
};
声明:本人所写内容全部参考hello-algo,仅用于个人复习。