C/C++泛型编程实现数据结构之栈


###栈是访问受限的线性表,遵循了后进先出的原则,只允许在栈顶进行操作。这里栈是一种数据结构。但是我们仍然可以对其进行存储结构上的划分。

在这里我们会把它分成顺序存储结构和链式存储结构两种方案进行划分,也就是说这里我们会编写两个模板类来实现栈的基本操作。

####栈的基本操作


  1. 判栈满(顺序存储结构)
  2. 判栈空
  3. 入栈
  4. 出栈
  5. 取栈顶元素
  6. 初始化栈

顺序栈在定义栈的时候要先给栈一个最大的存储空间,然后在这个基础上让他成为一个访问受限的线性表。后进先出LIFO(last in first out)线性表这也是本科数据结构和考研常考的知识点之一。


###以下为顺序栈的代码实现


template <typename DataType>
class Seq_Stack {
private:
int size;
int max_size;

protected:
DataType data = new DataType[max_size];

public:
Seq_Stack(int sizer = 10) {
size = -1;
max_size = sizer;
}
void Push(DataType data)
{
if (!Stack_Full()){ data[++size] = data;}
else {
cout << "the Stack is FULL!";
exit(0);
}
}
DataType Pop() {
if(!Stack_Empty()){
return data[size--];
}
else {
cout << "The stack is empty!" << endl;
exit(0);
}
}
bool Stack_Empty() {
if (this.size == -1) {
return true;
}
else return false;
}
int Stack_Full() {
if (this.size == max_size) { return true; }
else return false;
}
DataType GetTop() {
if (!Stack_Empty()) {
return data[size];
}
else {
cout << "The Stack is Empty!" << endl;
exit(0);
}
}

};


###以下为链式栈的代码实现


template <typename DataType>
class Link_Stack {
private:
typedef struct stacknode {
DataType data;
stacknode* next;
}StackNode;

protected:
StackNode * top;

public:
StackNode() { top = NULL; }

//判断栈是否为空
bool StackEmpty() {
return top == NULL;
}

StackNode* Push(DataType data) {
StackNode*p = (StackNode*)malloc(sizeof(StackNode));
p->data = data;
p->next = top;
top = p;
return top;
}

StackNode* Pop() {
StackNode* p = top;
if (StackEmpty()) { cout << "The stack is Empty!" << endl; exit(0); }
else {
top = p->next;
free(p);
return top;
}
}

DataType GetTop() {
if (StackEmpty()) {
cout << "The Stack is Empty!" << endl;
exiy(0);
}else {
return top->data;
}
}
};

以上即为栈的基本操作的类模板,但是重要的还是对栈的应用上。例如:圆括号匹配的检验,字符串回文的判断,数制转换的问题。特别是栈和递归有着密切而不可划分的联系。例如求解八皇后问题,斐波那契数列问题,阶乘计算时,都可以利用栈来代替递归,从而实现递归的操作而不会对内存空间造成太大的压力。(当然在这里能用迭代解决的问题就最好不要用递归。递归会占用大量的内存空间甚至会导致程序的异常终止。)

以下我将给出字符串回文的判断代码


####递归的应用:字符串回文的判断


bool symmetry(char str[]) {
Seq_Stack<char> S;
int j, k, i = 0;
while (str[i] != '\0')i++;
for (j = 0; j < i / 2; j++) {
S.Push(str[j]);
}
k = (i + 1) / 2;
for (j = k; j < i; j++) {
if (str[j] != S.GetTop()) {
S.Pop();
return false;
}
}
return true;
}