数据结构----栈的实现

1 阅读3分钟

栈的物理结构是一个数组,但是栈的逻辑结构是先进后出,类似于子弹入弹夹最后放入的子弹是最先打出的.相当于在数组的基础上加上了先进后出的规定.

C语言

#include<stdio.h>
#include<stdlib.h>
#define maxx 10

typedef struct {
	int* data;
	int top;
}Stack;

Stack InitStack() {
	Stack s;
	s.data = (int*)malloc(sizeof(int) * maxx);
	if (s.data == NULL) {
		printf_s("内存申请失败\n");
		s.top = -1;
		return s;
	}
	s.top = 0;
	return s;
}

void Push(Stack* s, int k) {
	if (s->top == maxx){
		printf_s("栈满,无法入栈\n");
		return;
	}
	s->data[s->top] = k;
	s->top++;
	return;
}

int IsEmpety(Stack* s) {
	if (s->top == 0) {
		return 1;
	}
	return 0;
}

void Pop(Stack* s)
{
	if (IsEmpety(s))
	{
		printf("栈空,无法出栈\n");
		return;
	}
	s->top--;
}

int Get(Stack s) {
	if (IsEmpety(&s))
	{
		printf("栈空,无法出栈\n");
		return;
	}
	return s.data[s.top - 1];
}

int main()
{
	Stack s = InitStack();
	Push(&s, 1);
	Push(&s, 2);
	Push(&s, 3);
	Pop(&s);
	Pop(&s);
	Pop(&s);
	printf("%d\n", Get(s));

	return 0;
}

对于栈的操作非常的简单初始化 入栈 判空 出栈 获取栈顶元素,在逻辑上栈是不能进行遍历的所以没有加入遍历打印的操作.

首先用一个结构体包装Stack栈,包括了数据域和栈顶"指针"两部分,这个栈顶指针实质是下标.

1.初始化栈用malloc申请内存,常规操作需要判断内存是否申请成功,如果失败的话我们需要让top == -1进行标记,然后直接return.如果申请成功则让top == 0.

2.入栈操作我们会对栈进行修改所以应该用地址传参Stack* s,先对栈进行判满,如果没满那么直接让s->data[s->top] = k,top这个栈顶指针其实指向的是栈顶元素的上一个位置,入栈后栈顶也需要上移所以top++.

3.判空函数直接看栈顶是否等于0,如果是的那么说明这是一个空栈,反之不是.

4.删除操作需要结合判空函数,如果不空那么我们直接让top--即可,在逻辑上删除这个元素.因为我们对栈中元素进行了操作所以这里也是地址传参.

5.获取栈顶元素我们没有对栈进行操作,我们只是想看看栈顶的元素是啥,所以可以用值传参,这个操作也需要对栈进行判空但我们传入的是一个值,所以里面的判空函数我们需要取地址&.然后直接返回栈顶的值即可.

栈的操作少而且简单,只要牢牢抓住先进后出这个规则即可.还需要注意我们的传参方式是取决于对栈的操作要不要改变栈.

C++

#include<iostream>
using namespace std;
#define maxx 10

class Stack {
private:
	int* data;
	int top;
public:
	Stack(){
		this->data = new int[maxx];
		this->top = 0;
	}

	void Push(int k) {
		if (top == maxx) {
			cout << "栈满,无法入栈" << endl;
			this->top = -1;
			return;
		}
		this->data[this->top] = k;
		this->top++;
		return;
	}

	int IsEmpety(){
		if (this->top == 0) {
			return 1;
		}
		return 0;
	}

	void Pop(){
		if (this->IsEmpety()) {
			cout << "栈空,无法删除" << endl;
			return;
		}
		this->top--;
		return;
	}

	int Get(){
		if (this->IsEmpety()) {
			cout << "栈空,无法删除" << endl;
			return -1;
		}
		return this->data[this->top - 1];
	}

	void Print() {
		if (IsEmpety()) {
			cout << "栈空" << endl;
			return;
		}
		cout << "栈内元素:";
		for (int i = 0; i < top; i++) {
			cout << data[i] << " ";
		}
		cout << endl;
	}
        ~Stack() {
        delete[] data; // 释放数组内存 
        }
};

int main() {
	// 1. 创建栈(自动调用构造函数)
	Stack s;

	// 2. 入栈
	s.Push(10);
	s.Push(20);
	s.Push(30);
	cout << "入栈 10、20、30 后:" << endl;
	s.Print(); // 打印栈

	// 3. 获取栈顶
	cout << "当前栈顶元素:" << s.Get() << endl;

	// 4. 出栈
	s.Pop();
	cout << "出栈一次后:" << endl;
	s.Print();

	s.Pop();
	s.Pop();
	cout << "出栈三次后:" << endl;
	s.Print();

	// 5. 空栈测试
	s.Pop();       // 栈空,无法删除
	s.Get();       // 栈空,无法获取

	return 0;
}

在C++中我们改用类来封装Stack相较于C语言中的结构体优点是不用再传 &s、不用管指针.