Implementation of stack
Stack is an important data structure. It is a linear structure with the characteristics of last in first out
Because there are two implementations of linear table, there are also two implementations of stack, namely sequential storage structure and chain storage structure. This paper gives an implementation based on chain storage structure
Storage structure of chain stack
Similar to the storage structure of single linked list, the storage image of chain stack also includes data field and pointer field. The storage structure is shown as follows:
class StackNode { T data_; StackNode* next_; };
To facilitate the management of a group of Stack nodes, you can define a Stack class as follows:
class Stack { private: StackNode<T>* ptr_; };
Main operations of stack
1. Initialization
The task of initialization is to construct an empty Stack. Unlike the linked list, there is no need to set a header node in the chain Stack, so you only need to empty the pointer at the top of the Stack. It can be realized by using the Stack class constructor, as follows:
Stack() { ptr_ = nullptr; }
2. Stack
Algorithm steps
- Create a stackenode object and point to it with the pointer ptr
- Set the node data field to data
- Insert the new node into the top of the stack
- Modify the stack top pointer
The specific implementation is as follows:
bool Stack::push(T data) { StackNode* ptr = new StackNode(data, ptr_); ptr_ = ptr; return true; }
3. Out of stack
Algorithm steps
- Judge whether the stack is empty. If it is empty, return false
- Assign the stack top element to data
- Temporarily save the space of the top element of the stack for release
- Modify the stack top pointer to point to the new stack top element
- Release the pointer of the original stack top element
The specific implementation is as follows:
bool Stack::pop(T& data) { if (ptr_ == nullptr) { return false; } data = ptr_->get_data(); StackNode* ptr = ptr_; ptr_ = ptr_->get_next(); delete ptr; return true; }
Where get_data and get_next is a function that returns the data element and pointer of the current node
4. Fetch stack top element
When the stack is not empty, the value of the current stack top element is returned. The specific implementation is as follows:
T Stack::get_top() { if (ptr_ != nullptr) return ptr_->get_data(); }
Of course, in addition to these, there are other interfaces, such as finding stack length, clearing stack, etc. I won't repeat them one by one here
In fact, so far, the data structure of the stack has been implemented, but there is room for improvement. If it is just such a simple implementation, it can always store only one type of data. If it is implemented with int, it can only store integer, and double can only store double precision floating-point. The scope of application is limited. It is unrealistic to define a stack for each data type (because there are user-defined types). Is there a method that can be defined once and is applicable to all types? Yes! C + + generic types
Here, we can make our stack store any data type by slightly modifying our code. The integration is as follows:
#pragma once template <typename T> class StackNode { public: StackNode() { next_ = nullptr; } StackNode(T data) { data_ = data; next_ = nullptr; } StackNode(T data, StackNode* next) { data_ = data; next_ = next; } T get_data() { return data_; } StackNode<T>* get_next() { return next_; } private: T data_; StackNode* next_; }; template <typename T> class Stack { public: bool push(T); bool pop(T&); T get_top(); void clear(); size_t length(); Stack() { ptr_ = nullptr; } private: StackNode<T>* ptr_; }; template <typename T> bool Stack<T>::push(T data) { StackNode<T>* ptr = new StackNode<T>(data, ptr_); ptr_ = ptr; return true; } template <typename T> bool Stack<T>::pop(T& data) { if (ptr_ == nullptr) { return false; } data = ptr_->get_data(); StackNode<T>* ptr = ptr_; ptr_ = ptr_->get_next(); delete ptr; return true; } template <typename T> T Stack<T>::get_top() { if (ptr_ != nullptr) return ptr_->get_data(); } template <typename T> void Stack<T>::clear() { while (ptr_) { StackNode<T>* ptr = ptr_; ptr_ = ptr_->get_next(); delete ptr; } } template <typename T> size_t Stack<T>::length() { size_t length = 0; StackNode<T>* ptr = ptr_; while (ptr) { ++length; ptr = ptr->get_next(); } return length; }