用隊列實現棧

問題描述:

請你僅用兩個隊列實現一個后入先出(LIFO)的棧,并支持普通隊列的全部四種操作(push、top、pop和empty)。

實現MyStack類:

  • void push(int x) 將元素x壓入棧頂。
  • int pop()移除并返回棧頂元素。
  • int top()返回棧頂元素。
  • boolean empty()如果棧是空的,返回true;否則,返回false。

解題思路:?

?

1. 入數據,往不為空的隊列入

2. 出數據,把不為空的隊列數據導入為空,直至只剩最后一個

解決本題之前,要先將隊列的各類接口函數準備好,隊列的接口函數我上一篇中提到了喔:

#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;//刪除數據和插入數據需要記錄頭結點和尾結點
typedef struct Queue
{QNode* head;QNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
//隊尾入
void QueuePush(Queue* pq, QDataType x);
//隊頭出
void QueuePop(Queue* pq);
//取隊頭的數據
QDataType QueueFront(Queue* pq);
//取隊尾的數據
QDataType QueueBack(Queue* pq);
//取數據的個數
int QueueSize(Queue* pq);
//判斷隊列是否為空
bool QueueEmpty(Queue* pq);void QueueInit(Queue* pq)
{assert(pq);pq->head = pq->tail = NULL;
}
void QueueDestory(Queue* pq)
{assert(pq);QNode* cur = pq->head;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;//返回初始狀態
}
//隊尾入
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;if (pq->tail == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}}
//隊頭出
void QueuePop(Queue* pq)
{assert(pq);assert(pq->head);//斷言隊列是否為空,為空就不可刪除,會有野指針if (pq->head->next == NULL)//當只有一個節點時,tail可能為野指針,tail指向已釋放的空間pq->tail = NULL;QNode* next = pq->head->next;free(pq->head);pq->head = next;}
//取隊頭的數據
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->head);return pq->head->data;
}
//取隊尾的數據
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->head);return pq->tail->data;
}
//取數據的個數
int QueueSize(Queue* pq)
{assert(pq);int size = 0;QNode* cur = pq->head;while (cur){size++;cur = cur->next;}return size;
}
//判斷隊列是否為空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

通過隊列創建棧:

typedef struct
{Queue q1;Queue q2;
}MyStack;
MyStack* myStackCreate()
{MyStack* ps = (MyStack*)malloc(sizeof(MyStack));if (ps == NULL){printf("malloc fail\n");exit(-1);}QueueInit(&ps->q1);//對隊列進行初始化QueueInit(&ps->q2);return ps;
}

在棧頂添加數據:

添加數據時,要在不為空的隊列里添加:

void myStackPush(MyStack* obj, int x)
{if (!QueueEmpty(&obj->q1)){QueuePush(&obj->q1,x);}else{QueuePush(&obj->q2, x);}
}

從棧頂處刪除數據并返回第一個數據:

int myStackPop(MyStack* obj)
{Queue* emptyQ = &obj->q1;Queue* nonemptyQ = &obj->q2;if (!QueueEmpty(&obj->q1)){emptyQ=&obj->q2;nonemptyQ=&obj->q1;}//倒數據while (QueueSize(nonemptyQ) > 1){//將不空的隊列的頭拷貝至空隊列中QueuePush(emptyQ, QueueFront(nonemptyQ));QueuePop(nonemptyQ);//刪除頭數據}int top = QueueFront(nonemptyQ);QueuePop(nonemptyQ);//刪除最后一個數據,實現了后進先出return top;
}

取棧頂的數據:

取不為空的隊列的隊尾數據:

int myStackTop(MyStack* obj)
{if (!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}

判斷棧是否為空:

bool myStackEmpty(MyStack* obj)
{return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

釋放棧:

先銷毀隊列,再釋放。

void myStackFree(MyStack* obj)
{QueueDestory(&obj->q1);QueueDestory(&obj->q2);free(obj);
}

整體代碼:

#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;//刪除數據和插入數據需要記錄頭結點和尾結點
typedef struct Queue
{QNode* head;QNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
//隊尾入
void QueuePush(Queue* pq, QDataType x);
//隊頭出
void QueuePop(Queue* pq);
//取隊頭的數據
QDataType QueueFront(Queue* pq);
//取隊尾的數據
QDataType QueueBack(Queue* pq);
//取數據的個數
int QueueSize(Queue* pq);
//判斷隊列是否為空
bool QueueEmpty(Queue* pq);void QueueInit(Queue* pq)
{assert(pq);pq->head = pq->tail = NULL;
}
void QueueDestory(Queue* pq)
{assert(pq);QNode* cur = pq->head;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;//返回初始狀態
}
//隊尾入
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;if (pq->tail == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}}
//隊頭出
void QueuePop(Queue* pq)
{assert(pq);assert(pq->head);//斷言隊列是否為空,為空就不可刪除,會有野指針if (pq->head->next == NULL)//當只有一個節點時,tail可能為野指針,tail指向已釋放的空間pq->tail = NULL;QNode* next = pq->head->next;free(pq->head);pq->head = next;}
//取隊頭的數據
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->head);return pq->head->data;
}
//取隊尾的數據
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->head);return pq->tail->data;
}
//取數據的個數
int QueueSize(Queue* pq)
{assert(pq);int size = 0;QNode* cur = pq->head;while (cur){size++;cur = cur->next;}return size;
}
//判斷隊列是否為空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}
typedef struct
{Queue q1;Queue q2;
}MyStack;
MyStack* myStackCreate()
{MyStack* ps = (MyStack*)malloc(sizeof(MyStack));if (ps == NULL){printf("malloc fail\n");exit(-1);}QueueInit(&ps->q1);QueueInit(&ps->q2);return ps;
}
void myStackPush(MyStack* obj, int x)
{if (!QueueEmpty(&obj->q1)){QueuePush(&obj->q1,x);}else{QueuePush(&obj->q2, x);}
}
//刪除數據且返回棧頂
int myStackPop(MyStack* obj)
{Queue* emptyQ = &obj->q1;Queue* nonemptyQ = &obj->q2;if (!QueueEmpty(&obj->q1)){emptyQ=&obj->q2;nonemptyQ=&obj->q1;}//倒數據while (QueueSize(nonemptyQ) > 1){//將不空的隊列的頭拷貝至空隊列中QueuePush(emptyQ, QueueFront(nonemptyQ));QueuePop(nonemptyQ);//刪除頭數據}int top = QueueFront(nonemptyQ);QueuePop(nonemptyQ);//刪除最后一個數據,實現了后進先出return top;
}int myStackTop(MyStack* obj)
{if (!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}
bool myStackEmpty(MyStack* obj)
{return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj)
{QueueDestory(&obj->q1);QueueDestory(&obj->q2);free(obj);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/208863.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/208863.shtml
英文地址,請注明出處:http://en.pswp.cn/news/208863.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java中線程的狀態是如何轉換的?

在 Java 中&#xff0c;線程有幾種狀態&#xff0c;主要包括 NEW&#xff08;新建&#xff09;、RUNNABLE&#xff08;可運行&#xff09;、BLOCKED&#xff08;阻塞&#xff09;、WAITING&#xff08;等待&#xff09;、TIMED_WAITING&#xff08;計時等待&#xff09;、和 TE…

Vue學習筆記-Vue3中的計算屬性與監視屬性

computed函數 import {reactive,computed} from vue export default {name: "DemoVue",setup(){//數據定義let person reactive({firstName : 李,lastName : 四,age:18,})//計算屬性定義-簡寫形式person.fullName computed(()>{return person.firstName-person…

手寫 Promise:深入理解異步編程的基石

手寫 Promise&#xff1a;深入理解異步編程的基石 本文將帶您逐步實現一個簡單的 Promise&#xff0c;以幫助您深入理解異步編程的基本概念。通過自己動手編寫 Promise 的過程&#xff0c;您將更好地理解 Promise 的工作原理和常見用法&#xff0c;并能夠應用于實際項目中。 …

什么是網站劫持

網站劫持是一種網絡安全威脅&#xff0c;它通過非法訪問或篡改網站的內容來獲取機密信息或者破壞計算機系統。如果您遇到了網站劫持問題&#xff0c;建議您立即聯系相關的安全機構或者技術支持團隊&#xff0c;以獲得更專業的幫助和解決方案。

探索 HTTPS:保障網絡通信的安全性

引言 HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;是一種安全的通信協議&#xff0c;用于在網絡上安全地傳輸數據。它是基于 HTTP 協議的擴展&#xff0c;通過加密通信實現了數據的保護和安全性。 功能介紹 加密數據傳輸&#xff1a; 使用加密技術對數…

Prism框架快速注冊帶有特性標簽的類型

前言 最近用Prims框架,真的是懶得手動注冊各種類型,不利于團隊開發工作,各種dll強耦合,后期維護還麻煩,這次我們帶來了一個快速注冊的類來快速提高開發效率。重點用到的就是通過反射出dll里面的類型,然后根據特性或者類型過濾來完成快速注冊的功能。 代碼 using Prism…

Angular 進階之四:SSR 應用場景與局限

應用場景 內容豐富&#xff0c;復雜交互的動態網頁&#xff0c;對首屏加載有要求的項目&#xff0c;對 seo 有要求的項目&#xff08;因為服務端第一次渲染的時候&#xff0c;已經把關鍵字和標題渲染到響應的 html 中了&#xff0c;爬蟲能夠抓取到此靜態內容&#xff0c;因此更…

【面試專題】MySQL篇①

1.MySQL中&#xff0c;如何定位慢查詢? ①介紹一下當時產生問題的場景&#xff08;我們當時的一個接口測試的時候非常的慢&#xff0c;壓測的結果大概5秒鐘&#xff09; ②我們系統中當時采用了運維工具&#xff08; Skywalking &#xff09;&#xff0c;可以監測出哪個接口…

PostgreSQL從小白到高手教程 - 第38講:數據庫備份

PostgreSQL從小白到專家&#xff0c;是從入門逐漸能力提升的一個系列教程&#xff0c;內容包括對PG基礎的認知、包括安裝使用、包括角色權限、包括維護管理、、等內容&#xff0c;希望對熱愛PG、學習PG的同學們有幫助&#xff0c;歡迎持續關注CUUG PG技術大講堂。 第38講&#…

running小程序重要技術流程文檔

一、項目文件說明&#xff1a; &#xff08;注&#xff1a;getMyMoney無用已刪除&#xff09; 二、重要文件介紹 1.reinfo.js&#xff1a;位于utils文件下&#xff0c;該文件封裝有統一的請求URL&#xff0c;和請求API同意封裝供頁面調用&#xff1b;調用時候需要在頁面上先…

【C語言】操作符詳解(一):進制轉換,原碼,反碼,補碼

目錄 操作符分類 2進制和進制轉換 2進制轉10進制 10進制轉2進制 2進制轉8進制和16進制 2進制轉8進制 2進制轉16進制 原碼、反碼、補碼 操作符分類 操作符中有一些操作符和二進制有關系&#xff0c;我們先鋪墊一下二進制的和進制轉換的知識。 2進制和進制轉換 其實我們經…

數據結構準備知識

struct&#xff08;結構體&#xff09; struct&#xff0c;或稱為結構體&#xff0c;是C語言中一種復合數據類型&#xff0c;它允許你將多個不同類型的數據項組合成一個單一的單位。這對于創建記錄或更復雜的數據結構非常有用。 結構體的定義語法如下&#xff1a; struct 結…

vertica主鍵列能插入重復值的處理辦法

問題描述 開發同事反饋在vertica中創建含主鍵列的表中插入重復數據時沒有進行校驗&#xff0c;插入重復值成功。經過測試著實可以插入重復值&#xff0c;這個坑有些不一樣。 創建表和插入語句如下&#xff1a; --創建表 CREATE TABLE dhhtest(ID VARCHAR(64) PRIMARY KEY );…

postgresql數據庫配置主從并配置ssl加密

1、先將postgresql數據庫主從配置好 參考&#xff1a;postgresql主從配置 2、在主節點配置ssl加密&#xff0c;使用navicat測試是否可以連接 參考&#xff1a;postgresql配置ssl 3、正常連接無誤后&#xff0c;將root.crt、server.crt、server.key復制到從數據庫節點的存儲…

使用Microsoft Dynamics AX 2012 - 5. 生產控制

生產控制的主要職責是生產成品。為了完成這項任務&#xff0c;制造業需要消耗物品和資源能力&#xff08;人員和機械&#xff09;。制造過程可能包括半成品的生產和庫存。半成品是指物品包括在成品材料清單中。 制造業的業務流程 根據公司的要求&#xff0c;您可以選擇申請Dy…

某馬點評——day04

達人探店 發布探店筆記 改一下&#xff0c;圖片保存路徑就可以直接運行測試了。 查看探店筆記 Service public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {Resourceprivate IUserService userService;Overridepublic Resu…

OpenCL學習筆記(二)手動編譯開發庫(win10+vs2019)

前言 有時需求比較特別&#xff0c;可能需要重新編譯opencl的sdk庫。本文檔簡單記錄下win10下&#xff0c;使用vs2019編譯的過程&#xff0c;有需要的小伙伴可以參考下 一、獲取源碼 項目地址&#xff1a;GitHub - KhronosGroup/OpenCL-SDK: OpenCL SDK 可以直接使用git命令…

一篇文章了解指針變量

字符指針變量 在指針的類型中我們知道有一種指針叫做字符指針 它的使用情況如下&#xff1a; #include<stdio.h> int main() {char pa w;char*p1&pa;*p1 a;printf("%c\n", *p1);return 0; } 在這段代碼當中&#xff0c;我們將‘w’字符的地址傳到了p…

vue3 自己寫一個月的日歷

效果圖 代碼 <template><div class"monthPage"><div class"calendar" v-loading"loading"><!-- 星期 --><div class"weekBox"><div v-for"(item, index) in dayArr" :key"index&q…

2.修改列名與列的數據類型

修改字段名與字段數據類型 1.修改字段名 有時&#xff0c;在我們建好一張表后會突然發現&#xff0c;哎呀&#xff01;字段名貌似寫錯了&#xff01;怎么辦&#xff1f;要刪了表再重新建一個新表嗎&#xff1f;還是要刪了這個字段再新建一個新的字段&#xff1f; 都不用&…