温故而知新 -> 数据结构 ->利用 队列 实现 栈 -> 程序实现1_利用结构体
本篇博客是基于 温故而知新 -> 数据结构 -> 线性表 ->队列 && 栈 中利用 队列 实现 栈 的理论知识进行程序实现!
其中结合了 温故而知新->数据结构->队列->程序实现1_利用结构体 中的代码,实现了 栈 的 增(入栈)删(出栈)查(栈顶元素)改(没写(~ ̄▽ ̄)~),判空,打印等操作!并附带了上述 队列 与 利用其所实现的栈 的对比实例以及对应的运行结果!
注意1:在利用队列实现栈的时候,分别采用了 一个队列 与 两个队列 的实现方式进行实现,该内容在下述程序中会有对比说明!
注意2:其中代码有很大冗余,且未考虑性能最优,读者有兴趣可进一步精简!
具体内容如下
(1)newQStack.h
#ifndef __NEWQSTACK_H_
#define __NEWQSTACK_H_
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
//队列:带有尾指针的单链表
typedef int QDataType;
typedef struct QNode
{
QDataType _data;
struct QNode* _next;
}QNode;
typedef struct Queue
{
//头尾指针
struct QNode * _head;
struct QNode * _tail;
int _size;
}Queue;
/* 方法一:利用一个队列实现时的 stack 结构体 */
//typedef struct{
// //队列成员
// struct Queue q;
//
//}MyStack;
/* 方法二:利用2个队列实现时的 stack 结构体 */
typedef struct{
//队列成员
struct Queue q1;
struct Queue q2;
}MyStack;
#endif
(2)main.c
#include"newQStack.h"
/* 实现队列 */
void initQueue(Queue * q)
{
if (q == NULL)
return;
q->_head = NULL;
q->_tail = NULL;
q->_size = 0;
}
struct QNode* creatNode(QDataType val)
{
struct QNode * newNode = (struct QNode*)malloc(sizeof(struct QNode));
newNode->_data = val;
newNode->_next = NULL;
}
void queuePush(Queue * q, QDataType val)
{
if (q == NULL)
return;
//尾插
struct QNode*node = creatNode(val);
//第一个节点
if (q->_head == NULL)
q->_head = q->_tail = node;
else
{
q->_tail->_next = node;
q->_tail = node;
}
++q->_size;
}
void queuePop(Queue * q)
{
//头删
if (q == NULL || q->_head == NULL)
return;
struct QNode * next = q->_head->_next;
free(q->_head);
q->_head = next;//q的头指向next
--q->_size;
if (q->_head == NULL)
q->_tail = NULL;//只有一个节点头删后,空队列
}
QDataType queueFront(Queue *q)//获得队首元素
{
return q->_head->_data;
}
QDataType queueRear(Queue *q)//获得队尾元素
{
return q->_tail->_data;
}
int queueEmpty(Queue *q)
{
return q->_head == NULL;
}
int queueSize(Queue *q)
{
if (q == NULL)
return 0;
return q->_size;
}
void queueDestory(Queue *q)
{
QNode *cur = q->_head;
while (cur)
{
QNode *next = cur->_next;
free(cur);
cur = next;
}
q->_head = q->_tail = NULL;
}
void queuePrint(Queue *q)
{
if (q == NULL || q->_head == NULL)
return;
QNode *cur = q->_head;
printf("队列元素数据:");
while (cur != NULL)
{
printf("%d ", cur->_data);
cur = cur->_next;
}printf("\n");
}
/* 利用队列实现栈 */
方法一:用一个队列实现
实现用队列构成栈
//
//MyStack *myStackCreate()
//{
// //struct MyStack st;//这种方法有问题,因为在函数中创建的是临时变量,
// //return &st; //函数一结束,该变量就会被销毁
//
// //动态创建
// MyStack *st = (MyStack*)malloc(sizeof(MyStack));
// initQueue(&(st->q));
// return st;
//}
//
//void myStackPush(MyStack *obj, int x)
//{
// queuePush(&obj->q, x);
//}
//
//int myStackPop(MyStack *obj)
//{
// int n = queueSize(&obj->q);
// while (n > 1)
// {//出栈是出栈顶元素,对应到队列就是最后一位元素
// //而队列又是先进先出,所以要出最后一个元素,则需将前面的元素先排出,再放进队列
// //从而实现栈的先进后出
// //出队,入队
// int front = queueFront(&obj->q);
// queuePop(&obj->q);
// queuePush(&obj->q, front);
// --n;
// }
// int top = queueFront(&obj->q);
// queuePop(&obj->q);
// return top;
//}
//
//int myStackTop(MyStack *obj)
//{
// return queueRear(&obj->q);//栈的栈顶就是队列的最后一位
// //因为栈是先进后出,队列是先进先出,徐构成先进后出,所以
// //栈顶就相当于队列的最后一位
//}
//
//bool myStackEmpty(MyStack *obj)
//{
// return queueEmpty(&obj->q);
//}
//
//void myStackDestory(MyStack *obj)
//{
// queueDestory(&obj->q);
// free(obj);
//}
//
//int myStackSize(MyStack *obj)
//{
// return queueSize(&obj->q);
//}
//
//void myStackPrint(MyStack *obj)
//{
// QDataType *data = (QDataType*)malloc(sizeof(QDataType)*queueSize(&obj->q));
// QNode *cur = obj->q._head;
// int i = 0;
// while (cur != NULL)
// {
// *(data + i) = cur->_data;
// cur = cur->_next;
// i++;
// }
// printf("栈内元素:");
// for (i = queueSize(&obj->q) - 1; i >= 0; i--)
// printf("%d ", *(data + i));
// printf("\n");
// free(data);
//}
//方法二:用二个队列实现
//实现用队列构成栈
MyStack *myStackCreate()
{
//struct MyStack st;//这种方法有问题,因为在函数中创建的是临时变量,
//return &st; //函数一结束,该变量就会被销毁
//动态创建
MyStack *st = (MyStack*)malloc(sizeof(MyStack));
initQueue(&(st->q1));
initQueue(&st->q2);
return st;
}
void myStackPush(MyStack *obj, int x)
{
//给非空队列进行入栈操作
if (!queueEmpty(&obj->q1))
queuePush(&obj->q1, x);
else
queuePush(&obj->q2, x);
}
void myStackPop(MyStack *obj)
{
int top;
if (!queueEmpty(&obj->q1))
{
int n = queueSize(&obj->q1);
while (n > 1)
{//出栈是出栈顶元素,对应到队列就是最后一位元素
//而队列又是先进先出,所以要出最后一个元素,则需将前面的元素先排出,再放进队列
//从而实现栈的先进后出
//出队,入队
int front = queueFront(&obj->q1);
queuePop(&obj->q1);
queuePush(&obj->q2, front);
--n;
}
int top = queueFront(&obj->q1);
queuePop(&obj->q1);
}
else
{
int n = queueSize(&obj->q2);
while (n > 1)
{//出栈是出栈顶元素,对应到队列就是最后一位元素
//而队列又是先进先出,所以要出最后一个元素,则需将前面的元素先排出,再放进队列
//从而实现栈的先进后出
//出队,入队
int front = queueFront(&obj->q2);
queuePop(&obj->q2);
queuePush(&obj->q1, front);
--n;
}
int top = queueFront(&obj->q2);
queuePop(&obj->q2);
}
}
int myStackTop(MyStack *obj)
{
if (!queueEmpty(&obj->q1))
return queueRear(&obj->q1);
else
return queueRear(&obj->q2);
//栈的栈顶就是队列的最后一位
//因为栈是先进后出,队列是先进先出,徐构成先进后出,所以
//栈顶就相当于队列的最后一位
}
bool myStackEmpty(MyStack *obj)
{
return queueEmpty(&obj->q1) && queueEmpty(&obj->q2);
}
int myStackSize(MyStack *obj)
{
return queueSize(&obj->q1) + queueSize(&obj->q2);
}
void myStackDestory(MyStack *obj)
{
queueDestory(&obj->q1);
queueDestory(&obj->q2);
free(obj);
}
void myStackPrint(MyStack *obj)
{
if (queueEmpty(&obj->q1) && queueEmpty(&obj->q2))
return;
if (!queueEmpty(&obj->q1))
{
QDataType *data = (QDataType*)malloc(sizeof(QDataType)*queueSize(&obj->q1));
QNode *cur = obj->q1._head;
int i = 0;
while (cur != NULL)
{
*(data + i) = cur->_data;
cur = cur->_next;
i++;
}
printf("栈内元素:");
for (i = queueSize(&obj->q1) - 1; i >= 0; i--)
printf("%d ", *(data + i));
printf("\n");
free(data);
}
else if (!queueEmpty(&obj->q2))
{
QDataType *data = (QDataType*)malloc(sizeof(QDataType)*queueSize(&obj->q2));
QNode *cur = obj->q2._head;
int i = 0;
while (cur != NULL)
{
*(data + i) = cur->_data;
cur = cur->_next;
i++;
}
printf("栈内元素:");
for (i = queueSize(&obj->q2) - 1; i >= 0; i--)
printf("%d ", *(data + i));
printf("\n");
free(data);
}
}
void test()
{
/* 实验队列操作 */
printf("实验队列操作:\n");
Queue q;
/* 实验入队 先进先出 */
initQueue(&q);
queuePush(&q, 1);
queuePush(&q, 2);
queuePush(&q, 3);
queuePush(&q, 4);
queuePrint(&q);// 1 2 3 4
/* 实验出队 */
queuePop(&q);
queuePrint(&q);// 2 3 4
queuePop(&q);
queuePrint(&q);// 3 4
//queuePop(&q);
//queuePrint(&q);// 4
//queuePop(&q);
//queuePrint(&q);// 空,因为空队列不打印
/* 实验队头与队尾元素 */
printf("此时队头元素为:%d \n", queueFront(&q));
printf("此时队尾元素为:%d \n", queueRear(&q));
/* 实验队列内元素个数 */
printf("此时队列元素个数为:%d \n", queueSize(&q));
/* 实验判空 */
printf("此时队列状态(0:非空,1:空):%d \n", queueEmpty(&q));
printf("\n");
/* 实验上述队列建成的栈 */
MyStack *s = myStackCreate();
/* 实验入栈 */
myStackPush(s, 1);
myStackPush(s, 2);
myStackPush(s, 3);
myStackPush(s, 4);
myStackPrint(s);// 4 3 2 1
/* 实验出栈 */
myStackPop(s);
myStackPrint(s);// 3 2 1
myStackPop(s);
myStackPrint(s);// 2 1
//myStackPop(s);
//myStackPrint(s);// 1
//myStackPop(s);
//myStackPrint(s);
/* 实验栈顶元素 */
printf("此时栈顶元素:%d \n", myStackTop(s));
/* 实验栈内元素个数与判空 */
printf("此时栈内元素个数为:%d \n", myStackSize(s));
printf("此时栈状态(0:非空,1:空):%d \n", myStackEmpty(s));
printf("\n");
}
int main()
{
test();
system("pause");
return 0;
}
(3)运行结果
注意3:在程序中虽然采取了两种栈的实现方式,但两种方式下的运行结果一致,此处就不再分别配图,如上图!
以上为本篇博客内容,若有问题,欢迎与笔者交流!
侵权删~