动手实现栈、队列

顺序存储

顺序队列推荐使用循环队列,防止在递归、循环过程中数组越界。代码长度主要因为注释和打印过程,本身很简单。

// StackQueue.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// 对于栈来说:top指向栈顶元素的位置
// 顺序队列得用循环队列
// 对于顺序队列,rear指向最后一个元素位置的后一个位置,牺牲一个节点来判断是满还是空
// 初始化:Q.front = Q.rear = 0
// 进队:Q.rear = (Q.rear + 1) % M
// 出队:Q.front = (Q.front + 1) % M
// 队空:Q.front == Q.rear
// 队满:(Q.rear + 1) % M == Q.front
// 队列长度: (Q.rear - Q.front + M) % M 

#include <iostream>

using namespace std;

const int M = 4;

struct record
{
    int x;
    int y;
};

typedef struct StackNode
{
    record data[M];
    int top;
}*SeStack;

typedef struct QueNode
{
    record data[M];
    int front, rear;
}*SeQue;

SeStack S = new StackNode;
SeQue Q = new QueNode;

void InitStack(SeStack S)
{
    S->top = -1;
}

void InitQue(SeQue Q)
{
    //考虑循环队列,首尾都为0,这样添加元素后rear++,front不动
    //队列:先进先出,尾进头出
    Q->front = Q->rear = 0;
}

void StackPush(SeStack S, record val)
{
    if (S->top < M)
    {
        S->top++;
        S->data[S->top] = val;
    }
    else
        cout << "Stack is full" << endl;
}

void QuePush(SeQue Q, record val)
{
    if ((Q->rear + 1) % M == Q->front)
        cout << "Queue is full" << endl;
    else
    {
        Q->data[Q->rear] = val;
        Q->rear = (Q->rear + 1) % M;
    }    
}

bool StackEmpty(SeStack S)
{
    if (S->top == -1)
        return true;
    else
        return false;
}

bool QueEmpty(SeQue Q)
{
    if (Q->front == Q->rear)
        return true;
    else
        return false;
}

void StackPop(SeStack S)
{
    if (!(StackEmpty(S)))
    {
        S->top--;
    }
    else
        cout << "Stack is empty" << endl;
}

void QuePop(SeQue Q)
{
    if (!QueEmpty(Q))
    {
        Q->front = (Q->front + 1) % M;
    }
    else
        cout << "Queue is Empty" << endl;
}

void StackPrint(SeStack S)
{
    for (int i = 0; i < S->top + 1; i++)
    {
        cout << "S->data[" << i << "].x:" << S->data[i].x << "\tS->data[" << i << "].y:" << S->data[i].y << endl;
    }
}

//int QueLength(SeQue Q)
//{
//    int length = (Q->rear - Q->front + M ) % M;
//    return length;
//}

void QuePrint(SeQue Q)
{
    int length = (Q->rear - Q->front + M) % M;
    if (QueEmpty(Q))
        cout << "Queue is Empty" << endl;
    else
    {
        for (int i = Q->front, j = 0; j < length; i = (i + 1) % M, j++)
        {
            cout << "Q->data[" << j << "].x:" << Q->data[i].x << "\tQ->data[" << j << "].y:" << Q->data[i].y << endl;
            //Q->front = (Q->front + 1) % M;
        }
    }
    
}

int main()
{
    record a{}, b{}, c{}, d{};
    a.x = 1;
    a.y = 1;
    b.x = 2;
    b.y = 2;
    c.x = 3;
    c.y = 3;
    d.x = 4;
    d.y = 4;
    cout << "InitStack" << endl;
    InitStack(S);
    cout << "push(a)" << endl;
    StackPush(S, a);
    StackPrint(S);
    cout << "push(b)" << endl;
    StackPush(S, b);
    StackPrint(S);
    cout << "pop()" << endl;
    StackPop(S);
    StackPrint(S);
    cout << "InitQue" << endl;
    InitQue(Q);
    cout << "push(a)" << endl;
    QuePush(Q, a);
    QuePrint(Q);
    cout << "push(b)" << endl;
    QuePush(Q, b);
    QuePrint(Q);
    cout << "puch(c、d)" << endl;
    QuePush(Q, c);
    QuePush(Q, d);
    QuePrint(Q);
    cout << "pop()" << endl;
    QuePop(Q);
    QuePrint(Q);
    cout << "push(d) again" << endl;
    QuePush(Q, d);
    QuePrint(Q);
    cout << "pop()" << endl;
    QuePop(Q);
    QuePrint(Q);
}

输出结果

 

链式存储

加的很多输出只是为了测试写的逻辑是否正确,使用时应该删除,链栈和链队列使用自定义节点record。

// Stack_Queue_DS.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

using namespace std;

//数据格式
struct record
{
	int x;
	int y;
};

typedef struct StackNode
{
	record data;
	StackNode* next;
}*LinkStack;

typedef struct QueNode
{
	record data;
	QueNode* next;
}*Que;

typedef struct
{
	Que front;
	Que rear;
}LinkQue;

/*
//为S new一个空间后,S notnull,如果不new,S null
LinkStack S = new StackNode;
*/
//这样声名的话,对应的要用顺序插入法,否则会报nullptr
LinkStack S;
LinkStack S1;
//LinkStack S2;

LinkQue Q;
LinkQue Q1;

//带头结点的方法
void StackPush(LinkStack& S, record val)
{
	//这里临时节点p必须申请空间,否则p只是一个指针(地址),不能使用p->data,会报错:未初始化的局部变量p
	LinkStack p = new StackNode;
	/*p->data.x = val.x;
	p->data.y = val.y;*/
	p->data = val;
	/*
	//头插法
	p->next = S->next;
	S->next = p;
	*/
	
	//直接插入法
	p->next = S;
	S = p;

}

//测试通过,函数正确
bool StackEmpty(LinkStack& S)
{
	if (S == NULL) 
	{
		//cout << "判空函数这样认为:NULL" << endl;
		return true;
	}	
	else
	{
		//cout << "判空函数这样认为:notNULL" << endl;
		return false;
	}
		
}

void StackPop(LinkStack& S)
{
	if (StackEmpty(S))
	{
		cout << "栈为空!" << endl;
		return;
	}	
	else
	{
		LinkStack temp = new StackNode;
		temp = S;
		S = S->next;
		delete temp;
	}
}

void StackPrint(LinkStack& S)
{
	while(!StackEmpty(S))
	{
		cout << "****" << endl;
		StackPush(S1, S->data);
		cout  << "S->data.x:" << S->data.x << "    S->data.y:" << S->data.y << endl;
		StackPop(S);
	}
	while(!StackEmpty(S1))
	{
		cout << "++++" << endl;
		cout << "S1->data.x:" << S1->data.x << "    S1->data.y:" << S1->data.y << endl;
		StackPush(S, S1->data);
		StackPop(S1);
	}
}

void InitQue(LinkQue& Q)
{
	Q.front = Q.rear= new QueNode;
}

void QuePush(LinkQue& Q, record val)
{
	Que temp = new QueNode;
	temp->data = val;
	Q.rear->next = temp;
	Q.rear = temp;
}

bool QueEmpty(LinkQue& Q)
{
	if (Q.front == Q.rear)
		return true;
	else
		return false;
}

void QuePop(LinkQue& Q)
{
	if(!QueEmpty(Q))
	{
		//删除的时候好像可以不申请临时节点的空间
		Que temp;
		temp = Q.front;
		Q.front = Q.front->next;
		delete temp;
	}
}

//队列:先进先出!尾进头出!!
void PrintQue(LinkQue& Q)
{
	while(!QueEmpty(Q))
	{
		cout << "*****************" << endl;
		cout << "Q.front->next->date.x:" << Q.front->next->data.x << "  Q.front->next->data.y:" << Q.front->next->data.y << endl;
		QuePush(Q1, Q.front->next->data);
		//QuePop(Q);//这是队列又不是栈!!!
		Q.front = Q.front->next;
	}
	while(!QueEmpty(Q1))
	{
		cout << "+++++++++++++++++" << endl;
		cout << "Q1.front->next->data.x:" << Q1.front->next->data.x << "  Q1.front->next->data.y:" << Q1.front->next->data.y << endl;
		QuePush(Q, Q1.front->next->data);
		Q1.front = Q1.front->next;
	}
}


void main() {
	//S = NULL;
	//S->next = NULL;
	/*if (S == NULL)
		cout << "NULL" << endl;
	else
		cout << "NotNULL" << endl;
	StackEmpty(S);*/
	record a{};
	a.x = 1;
	a.y = 2;
	record b{};
	b.x = 3;
	b.y = 4;
	StackPush(S, a);
	StackPush(S, b);
	StackPrint(S);
	/*if (S == NULL)
		cout << "NULL" << endl;
	else
		cout << "NotNULL" << endl;
	StackEmpty(S);*/
	StackPop(S);
	StackPrint(S);
	StackPrint(S);
	//指针测试
	int x = 5;
	//int* p = new int;
	int* p = &x;
	cout << p << "   " << *p << "   " << &p << endl;
	//delete p;
	//cout << p << "   " << *p << "   " << &p << endl;
	//如果int* p =new int,报错:引发了异常: 读取访问权限冲突。
	//p 是 0x8123。问题:空指针/野指针,也就是说delete了
	//如果int* p = &x,报错:(会自动跳到一个delete_scalar.cpp的文件内)已在 Stack_Queue_DS.exe 中执行断点指令(__debugbreak()语句或类似调用)。
	//问题:内存越界,但是注释掉打印仍然这么报错,delete注释就不再报错,推测为没有申请空间不能delete,但是为什么pop函数里可以这样?
	//指针到底需不需要delete,是由其指向的内存区域决定的
	//栈中的变量,是由程序自动进行管理的,当变量作用域结束后,程序就会自动释放,因此其内存区域不需要手动delete
	//堆则是一种容量大,但效率很低的内存区域,需要用户手动去进行管理(自动管理会影响程序性能),必须手动delete
	//所以答案就是,指向栈内存的指针不需要delete,指向堆内存的指针需要delete
	InitQue(Q);
	InitQue(Q1);
	QuePush(Q, a);
	QuePush(Q, b);
	PrintQue(Q);
	QuePop(Q);
	PrintQue(Q);
}

输出结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值