由于之前看了牛客网的数据结构和算法的课程知道了左神,现在顺便就买了他的书做做题吧,虽然书的题解都是java实现的,但好在用c++实现难度不大。
第一章 栈和队列
题目一:设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) – 将元素 x 推入栈中。
pop() – 删除栈顶的元素。
top() – 获取栈顶元素。
getMin() – 检索栈中的最小元素。
class MinStack {
public:
MinStack() {
}
void push(int x) {
databace.push(x);
if (stackMin.empty()||x<=stackMin.top())
{
stackMin.push(x);
}
else{
stackMin.push(stackMin.top());
}
}
void pop() {
databace.pop();
stackMin.pop();
}
int top() {
return databace.top();
}
int getMin() {
return stackMin.top();
}
private:
//用database和stackMin两个栈实现
stack<int> databace;//保存当前栈中的元素
stack<int> stackMin;//保存每一步的最小值
};
题目二:使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。
class MyQueue {
public:
int a;
MyQueue() {
}
void push(int x) {
stackpush.push(x);
}
void push1(){
while(!stackpush.empty()){
stackpop.push(stackpush.top());
stackpush.pop();
}
}
int pop() {
if (stackpop.empty())
{
while (!stackpush.empty())
{
push1();
}
}
a=stackpop.top();
stackpop.pop();
return a;
}
int peek() {
if (stackpop.empty())
{
while(!stackpush.empty()){
push1();
}
}
a=stackpop.top();
return a;
}
bool empty() {
if (stackpop.empty()&&stackpush.empty())
{
return true;
}else return false;
}
private:
//两个栈实现队列:1.如果stackpush要往stackpop中压入数据,那么必须一次性把stackpush中的数据全部压入。
// 2.如果stackpop不为空,stackpush绝对不能向stackpop中压入数据
stack<int> stackpush;//压入栈,在压入数据是只往这个栈中压入
stack<int> stackpop;//弹出栈,在弹出数据时只从这个栈弹出
};
题目三:如何仅用递归函数和栈操作逆序一个栈:一个栈依次压入1,2,3,4,5,那么从栈顶到栈底分别为5,4,3,2,1。将这个栈转置后,从栈顶到栈底为1,2,3,4,5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数据结构。
#include "stdafx.h"
#include <iostream>
#include <stack>
using namespace std;
//递归函数一:将栈底元素返回并删除
int getAndRemoveLastElement(stack<int> &a){ //pass-by-reference
int last=a.top();
a.pop();
if (a.empty())
{
return last;
}
else{
int b=getAndRemoveLastElement(a);
a.push(last);
return b;
}
}
//递归函数二:逆序一个栈,就是题目要求实现的方法,该方法用到了第一个递归函数
void reverse(stack<int> &stack){ //pass-by-reference
if(stack.empty()){
return ;
}
int c=getAndRemoveLastElement(stack);
reverse(stack);
stack.push(c);
}
int main(){
stack<int> a;
for (int s=0;s<10;++s)
{
a.push(s);
}
reverse(a);
int b;
for (int s=0;s<10;++s)
{
b=a.top();
a.pop();
std::cout<<b<<" "<<std::endl;
}
return 0;
}
题目四:猫狗队列:
宠物、狗和猫的类如下:
public class Pet{
private String type;
public Pet(String type){
this.type = type;
}
public String getPetType(){
return this.type;
}
}
public class Dog extends Pet {
public Dog(){
super("dog");
}
}
public class Cat extends Pet{
public Cat(){
super("cat");
}
}
实现一种猫狗队列的结构,要求如下:
1.用户可以调用add方法将cat类或者dog类的实例放入队列中;
2.用户可以调用pollAll方法,将队列中所有的实例按照队列的先后顺序依次弹出;
3.用户可以调用pollDog方法,将队列中dog类的实例按照队列的先后顺序依次弹出;
4.用户可以调用pollCat方法,将队列中cat类的实例按照队列的先后顺序依次弹出;
5.用户可以调用isEmpty方法,检查队列中是否还有dog和cat的实例;
6.用户可以调用isDogEmpty方法,检查队列中是否还有do的实例;
7.用户可以调用isCatEmpty方法,检查队列中是否还有cat的实例。
#pragma once
#include <string>
#include <queue>
#include <iostream>
using namespace std;
//本题应实现将不同的实例盖上时间戳的方法,但是又不能改变用户本身的类,所以定义一个新的类
//c++实现宠物、猫、狗类
class Pet{
public:
Pet(string type){
this->type = type;
}
Pet(){};
string getPetType(){
return this->type;
}
private:
string type;
};
class Dog : public Pet {
public:
Dog():Pet("dog"){//这里原先代码是:Dog(){Pet::Pet("dog")}报错,原因是:在构造派类时,会先调用基类的构造函数,再执行派生类构造函数。而你的写法是告诉程序在执行派生类构造函数时,把基类的构造函数作为一个普通函数进行调用。而在派生类构造函数之前调用的基类构造函数并没有声明,因此会报错
}
};
class Cat : public Pet{
public:
Cat():Pet("cat"){
}
};
//分割-----------------------------------------------------------------------------
//定义的新的类peterPetQueue
class peterPetQueue{
public:
long getLong(){
return b;
}
peterPetQueue(Pet a1,long b1){
this->a=a1;
this->b=b1;
}
private:
Pet a; //用户原有的实例
long b;//时间戳
};
//大体来说,首先有一个不断累加的数据项,用来表示实例进队列的时间;同时有两个队列,一个是只放dog类实例的队列DogQueue,同理另一个为CatQueue
class catAndDog
{
public:
catAndDog(){
this->count1=0;
}
void add(Pet item){//这里原先报错:Error LNK2001 无法解析的外部符号 原因是我在基类Pet中的Pet()只是声明,没有给出定义
if (item.getPetType()=="cat")
{
CatQueue.push(peterPetQueue(item,count1++));
}
else{
DogQueue.push(peterPetQueue(item,count1++));
}
}
void pollDog(){
while(!DogQueue.empty()){
DogQueue.pop();
}
}
void pollCat(){
while(!CatQueue.empty())
CatQueue.pop();
}
bool isEmpty(){
if (CatQueue.empty()&&DogQueue.empty())
{
return true;
}
else return false;
}
bool isDogEmpty(){
if (DogQueue.empty())
{
return true;
}
else return false;
}
bool isCatEmpty(){
if (CatQueue.empty())
{
return true;
}
else return false;
}
void pollAll(){
while(!DogQueue.empty()&&!CatQueue.empty()){
if (DogQueue.front().getLong()>CatQueue.front().getLong())
{
CatQueue.pop();
}
else DogQueue.pop();
}
if (!DogQueue.empty())
{
DogQueue.pop();
}
if (!CatQueue.empty())
{
CatQueue.pop();
}
}
private:
queue<peterPetQueue> CatQueue;
queue<peterPetQueue> DogQueue;
long count1;
};