数据结构和算法(03)---栈和队列(c++)

目录

  • 数据结构:
    • 逻辑结构:数组,栈,队列,字符串,树,图
    • 存储结构:顺序存储,链式存储
  • C++常用的数据结构有:string , stack , queue , deque , vector , list , map , iterators.

一.栈

栈可以看成一种特殊的线性表,特殊之处在于只能在表头或者表尾进行删除和插入操作。

1.栈的基本操作

push(): 向栈内压入一个成员;
pop(): 从栈顶弹出一个成员;
empty(): 如果栈为空返回true,否则返回false;
top(): 返回栈顶,但不删除成员;
size(): 返回栈内元素的大小

例子:

#include <iostream>
#include <stack>

using namespace std;

int main(){
	//定义一个整形的栈
	stack <int> mStack;
	cout<<"the size of mStack is:"<<mStack.size()<<endl;
	//向栈中加入元素
	mStack.push(1);
	mStack.push(2);
	mStack.push(3);
	mStack.push(4);
	cout<<"after push , the size of mStack is:"<<mStack.size()<<endl;
	//弹出栈中的内容
	while(!mStack.empty()){    //栈的遍历 
		cout<<"the data will be pop is:"<<mStack.top()<<endl;
		mStack.pop();
		cout<<"after pop ,the len of stack is:"<<mStack.size()<<endl;
	}
	
	
	
//	for(int i =0 ; i < 4;i++){
//		mStack.pop();  //出栈 
//		cout<<"the "<<i<<" pop is:"<<mStack.top()<<endl;
//		cout<<"the len "<<i<<" pop is:"<<mStack.size()<<endl;
//	}
	 
	
	return 0;
}

the size of mStack is:0
after push , the size of mStack is:4
the data will be pop is:4
after pop ,the len of stack is:3
the data will be pop is:3
after pop ,the len of stack is:2
the data will be pop is:2
after pop ,the len of stack is:1
the data will be pop is:1
after pop ,the len of stack is:0

2.使用C++模板类实现栈

虽然C++自带了stack的模板类,也实现了大部分的栈的操作,但是我们还是需要自己实现栈这种逻辑结构。

#include <iostream>
#include <stack>

using namespace std;

#define MAXSIZE 0XFFFF

template<class T>
class myStack{

private:
 
	int top;  //栈顶指针,顺序存储中位数组的下标,所以必须为整形 
	T* my_s;  //栈的存储空间指针 
	int maxSize;  //栈最大的存储空间 

public:
	//默认的构造函数 
	myStack():top(-1),maxSize(MAXSIZE){
		my_s = new T[maxSize];  //为栈申请存储
		if(my_s == NULL){
			cerr<<"内存分配失败!"<<endl;
			exit(1);
		} 
	}
	//带参数的构造函数 
	myStack(int size):top(-1),maxSize(size){
		my_s = new T[maxSize]; //为栈申请存储
		if(my_s == NULL){
			cerr<<"内存分配失败!"<<endl;
			exit(1);
		}
	} 
	~myStack(){
		cout<<"delete the stack!"<<endl;
		delete [] my_s;  //删除整个栈 
	}
	
	bool isEmpty();//判空函数
	void push(T data); //压栈函数
	void pop();    //出栈函数
	T getTopValue();  //取出栈顶元素 
	int size(); //判断栈的大小 
};

//函数定义 
template<class T>
bool myStack<T>::isEmpty(){
	if(top==-1){		//栈顶指针为-1表示栈空 
		return true;
	}
	else{
		return false;
	}
} 

template<class T>
void myStack<T>::push(T data){
	if((top+1) < maxSize){   
		my_s[++top] = data;  //先将栈顶指针加一,然后在给栈顶赋值 
	}
	else{
		cout<<"栈满!"<<endl;
	}
} 

template<class T>
void myStack<T>::pop(){
	if(top == -1){
		cout<<"栈空!!"<<endl;
	}else{
		top--;  //栈顶指针减一 
	}
} 

template<class T>
T myStack<T>::getTopValue(){
	if(top == -1){
		cout<<"栈空!!"<<endl;
	}else{
		return my_s[top];
	}
} 

template<class T>
int myStack<T>::size(){
	return top+1;
} 

 
int main(){
	
//	myStack<int> mStack;  //创建一个栈
//	cout<<"The size of mStack is "<<mStack.size()<<endl;
//	//压栈
//	mStack.push(1);
//	mStack.push(2);
//	mStack.push(3);
//	mStack.push(4);
//	cout<<"After push , the size of mStack is "<<mStack.size()<<endl;
//	while(!mStack.isEmpty()){
//		cout<<"the top value of mStack is : "<<mStack.getTopValue()<<endl;
//		mStack.pop();
//		cout<<"After pop , the size of mStack is "<<mStack.size()<<endl;	
//	}
	myStack<double> mStack;  //创建一个栈
	cout<<"The size of mStack is "<<mStack.size()<<endl;
	//压栈
	mStack.push(1.1);
	mStack.push(2.4);
	mStack.push(3.5);
	mStack.push(4.8);
	cout<<"After push , the size of mStack is "<<mStack.size()<<endl;
	//出栈 
	while(!mStack.isEmpty()){
		cout<<"the top value of mStack is : "<<mStack.getTopValue()<<endl;
		mStack.pop();
		cout<<"After pop , the size of mStack is "<<mStack.size()<<endl;	
	}
	
	return 0;
}

The size of mStack is 0
After push , the size of mStack is 4
the top value of mStack is : 4.8
After pop , the size of mStack is 3
the top value of mStack is : 3.5
After pop , the size of mStack is 2
the top value of mStack is : 2.4
After pop , the size of mStack is 1
the top value of mStack is : 1.1
After pop , the size of mStack is 0
delete the stack!


二.队列

队列也是一种特殊的线性表,它只允许在表的一头插入元素(队尾),表的另一头删除元素(队头)。

1.队列的基本操作

q.empty() 如果队列为空返回true,否则返回false
q.size() 返回队列中元素的个数
q.pop() 删除队列首元素但不返回其值
q.push() 在队尾压入新元素
q.front() 返回队首元素的值,但不删除该元素
q.back() 返回队列尾元素的值,但不删除该元素

例子(使用c++自带的库实现的)

#include <iostream>
#include <queue>

using namespace std;
 
int main(){
	queue<int> mQueue; //创建一个新的队列
	cout<<"the size of mQueue is: "<<mQueue.size()<<endl;
	cout<<"mQueue is empty?: "<<mQueue.empty()<<endl;
	//入队
	mQueue.push(1); 
	mQueue.push(2);
	mQueue.push(3);
	mQueue.push(4);
	cout<<"after push , the size of mQueue is: "<<mQueue.size()<<endl;
	cout<<"the front data of mQueue is: "<<mQueue.front()<<endl;
	cout<<"the back data of mQueue is: "<<mQueue.back()<<endl;
	
	while(!mQueue.empty()){
		cout<<"the front data of mQueue is: "<<mQueue.front()<<endl;
		mQueue.pop();
		cout<<"after pop , the size of mQueue is: "<<mQueue.size()<<endl;	
	}
	 
	return 0;
}

the size of mQueue is: 0
mQueue is empty?: 1
after push , the size of mQueue is: 4
the front data of mQueue is: 1
the back data of mQueue is: 4
the front data of mQueue is: 1
after pop , the size of mQueue is: 3
the front data of mQueue is: 2
after pop , the size of mQueue is: 2
the front data of mQueue is: 3
after pop , the size of mQueue is: 1
the front data of mQueue is: 4
after pop , the size of mQueue is: 0

注意

由于单端队列的空间利用率非常低,几乎就是一次性的(只要入队满了,然后全部出队后,便不可再用),所以此处就不讨论自己实现单端队列了。

2.循环队列

循环队列中判断队空的方法是判断front==rear,队满的方法是判断front=(rear+1)%maxSize。
可以解决单端队列中空间一次性消耗的问题

循环队列顺序存储

#include <iostream>
#include <queue>

using namespace std;

#define MAXSIZE 0XFFFF  

template<class T>
class myQueue{

private:
	
	int front,rear; //队头和队尾元素 
	T* my_q;    //队列的存储空间 
	int maxSize;  //最大的队列存储空间

public:
	//默认构造函数 
	myQueue():front(-1),rear(-1),maxSize(MAXSIZE){
		my_q = new T[maxSize];  //申请内存
		if(my_q == NULL){
			cerr<<"内存申请失败!!"<<endl;
			exit(1);
		} 
	}
	//带参数的构造函数 
	myQueue(int size):front(-1),rear(-1),maxSize(size){
		my_q = new T[maxSize];  //申请内存
		if(my_q == NULL){
			cerr<<"内存申请失败!!"<<endl;
			exit(1);
		} 
	}
	//析构函数 
	~myQueue(){
		cout<<"delete the queue!!!"<<endl;
		delete [] my_q;
	} 
	//操作函数
	bool isEmpty();  //判空 
	void push(T data); //入队操作 
	void pop();   //出队操作 
	T getFrontData(); //获取队头元素 
	T getRearData();  //获取队尾元素 
	int size();	 //获取队列长度 
};

template<class T>
bool myQueue<T>::isEmpty(){
	if(front == rear){  //判空条件 
		return true;
	}else{
		return false;
	}
}

template<class T>
void myQueue<T>::push(T data){
	if((rear+1)%maxSize == front){  //队列满时候的条件 
		cout<<"队列满了!!"<<endl;
	}else{
		my_q[rear] = data;  //首先队尾元素赋值 
		rear = (rear+1) % maxSize;
	}
}

template<class T>
void myQueue<T>::pop(){
	if(rear == front){
		cout<<"队列为空!!"<<endl;
	}else{
		front = (front+1) % maxSize;  //队头指针加一 
	}
}

template<class T>
T myQueue<T>::getFrontData(){
	if(rear == front){
		cout<<"队列为空!!"<<endl;
	}else{
		return my_q[front];
	}
}

template<class T>
T myQueue<T>::getRearData(){
	if(rear == front){
		cout<<"队列为空!!"<<endl;
	}else{
		return my_q[rear];
	}
}

template<class T>
int myQueue<T>::size(){
	return (rear-front+maxSize)%maxSize;  //队列长度计算 
}

//main loop 
int main(){
	
	myQueue<int> mQueue;//创建一个新的队列
	cout<<"the size of mQueue is: "<<mQueue.size()<<endl;
	cout<<"mQueue is empty?: "<<mQueue.isEmpty()<<endl;
	//入队
	mQueue.push(1); 
	mQueue.push(2); 
	mQueue.push(3); 
	mQueue.push(4);  
	cout<<"after push , the size of mQueue is: "<<mQueue.size()<<endl;
	cout<<"the front data of mQueue is: "<<mQueue.getFrontData()<<endl;
	cout<<"the back data of mQueue is: "<<mQueue.getRearData()<<endl;
	
	while(!mQueue.isEmpty()){
		cout<<"the front data of mQueue is: "<<mQueue.getFrontData()<<endl;
		mQueue.pop();
		cout<<"after pop , the size of mQueue is: "<<mQueue.size()<<endl;	
	}
		 
	return 0;
}

the size of mQueue is: 0
mQueue is empty?: 1
after push , the size of mQueue is: 4
the front data of mQueue is: 1
the back data of mQueue is: 0
the front data of mQueue is: 1
after pop , the size of mQueue is: 3
the front data of mQueue is: 2
after pop , the size of mQueue is: 2
the front data of mQueue is: 3
after pop , the size of mQueue is: 1
the front data of mQueue is: 4
after pop , the size of mQueue is: 0
delete the queue!!!

循环队列链式存储

#include <iostream>
using namespace std;
template<class T> 
struct LinkNode{
    T data;
    LinkNode<T> *link;
    LinkNode(T& x,LinkNode<T> *l=NULL){
        data=x;
        link=l;
    }
};
template<class T>
class LinkedQueue{
    protected:
        LinkNode<T> *front,*rear;
    public:
        LinkedQueue(){
            front=rear=NULL;
        }
        ~LinkedQueue(){
            makeEmpty();
        }
        bool enQueue(T& x){
            if(front==NULL)
                front=rear=new LinkNode<T>(x);
            else{
                rear=rear->link=new LinkNode<T>(x);
            }
            return true;
        }
        bool deQueue(T& x){
            if(isEmpty()) return false;
            LinkNode<T> *p=front;
            x=front->data;
            front=front->link;
            delete p;
            return true;
        }
        bool getFront(T& x)const{
            if(isEmpty()) return false;
            x=front->data;
            return true;
        }
        void makeEmpty(){
            LinkNode<T> *p;
            while(front!=NULL){
                p=front;
                front=front->link;
                delete p;
            }
        }
        bool isEmpty()const{
            return (front==NULL)?true:false;
        }
        int getSize()const{
            LinkNode<T> *p;
            int count=0;
            p=front;
            while(p!=NULL){
                count++;
                p=p->link;
            } 
        return count;
        }
}; 
void menu(){
    cout<<"1.入队"<<endl;
    cout<<"2.获取队首元素"<<endl;
    cout<<"3.出队"<<endl;
    cout<<"4.队列置空"<<endl;
    cout<<"5.获取队中元素数量"<<endl;
    cout<<"6.退出"<<endl;
} 

void function(int num,LinkedQueue<int> *lq){
    switch(num){
        int x;
        case 1:
            cin>>x;
            lq->enQueue(x);
            break;
        case 2:
            lq->getFront(x);
            cout<<x<<endl;
            break;
        case 3:
            lq->deQueue(x);
            break;
        case 4:
            lq->makeEmpty();
            break;
        case 5:
            x=lq->getSize();
            cout<<x<<endl;
            break;    
        default:
            exit(1);
    }
}
int main(int argc, char** argv) {
    LinkedQueue<int> *lq=new LinkedQueue<int>;
    int num;
    while(true){
        menu();
        cin>>num;
        function(num,lq);
    } 
    delete lq;
    return 0; 
}

3.双端队列

可以在两头进行插入和删除操作的队列

deque k; 定义一个deque的变量(定义时已经初始化)
例如: deque k;

k.empty() ------ 查看是否为空范例,是的话返回1,不是返回0
k.clear() ------ 清除队列里的所有数据
k.push_front(i)------ 从已有元素前面增加元素i(队伍大小不预设)
k.push_back(i) ------ 从已有元素后面增加元素i(队伍大小不预设)
k.pop_front() ------ 清除第一个元素
k.pop_back() ------ 清除最后一个元素
k.front() ------ 显示第一个元素
k.back() ------ 显示最后一个元素
k.size() ------ 输出现有元素的个数

例子(使用c++自带的库实现的)

#include <iostream>
#include <deque>

using namespace std;

//main loop 
int main(){
	
	deque<int> myDeque;//创建一个双端队列
	cout<<"the size of myDeque is: "<<myDeque.size()<<endl;
	cout<<"myDeque is empty? : "<<myDeque.empty()<<endl; 
	//从对头插入元素
	myDeque.push_front(1);
	myDeque.push_front(2);
	myDeque.push_front(4);
	myDeque.push_front(3);
	//从队尾插入 
	myDeque.push_back(0);
	myDeque.push_back(-1);
	myDeque.push_back(-1);
	myDeque.push_back(-3);
	//从队头出队
	deque<int> tempQueue = myDeque;
	while(!tempQueue.empty()){
		cout<<"the front data of queue is: "<<tempQueue.front()<<endl;
		tempQueue.pop_front();
		cout<<"the size of myDeque is: "<<tempQueue.size()<<endl;
	} 
	//从队尾出队
	deque<int> tempQueue1 = myDeque;
	while(!tempQueue1.empty()){
		cout<<"the front data of queue is: "<<tempQueue1.back()<<endl;
		tempQueue1.pop_back();
		cout<<"the size of myDeque is: "<<tempQueue1.size()<<endl;
	} 
	//清空队列
	deque<int> tempQueue2 = myDeque;
	cout<<"the size of myDeque is: "<<tempQueue2.size()<<endl;
	tempQueue2.clear();
	cout<<"the size of myDeque1 is: "<<tempQueue2.size()<<endl;
		 
	return 0;
}

the size of myDeque is: 0
myDeque is empty? : 1
the front data of queue is: 3
the size of myDeque is: 7
the front data of queue is: 4
the size of myDeque is: 6
the front data of queue is: 2
the size of myDeque is: 5
the front data of queue is: 1
the size of myDeque is: 4
the front data of queue is: 0
the size of myDeque is: 3
the front data of queue is: -1
the size of myDeque is: 2
the front data of queue is: -1
the size of myDeque is: 1
the front data of queue is: -3
the size of myDeque is: 0
the front data of queue is: -3
the size of myDeque is: 7
the front data of queue is: -1
the size of myDeque is: 6
the front data of queue is: -1
the size of myDeque is: 5
the front data of queue is: 0
the size of myDeque is: 4
the front data of queue is: 1
the size of myDeque is: 3
the front data of queue is: 2
the size of myDeque is: 2
the front data of queue is: 4
the size of myDeque is: 1
the front data of queue is: 3
the size of myDeque is: 0
the size of myDeque is: 8
the size of myDeque1 is: 0


猜你喜欢

转载自blog.csdn.net/wangzi11111111/article/details/88410658