文章目录
- 目录
- 一.栈
- 1.栈的基本操作
- 2.使用C++模板类实现栈
- 二.队列
- 1.队列的基本操作
- 2.循环队列
- **循环队列顺序存储**
- **循环队列链式存储**
- 3.双端队列
目录
- 数据结构:
- 逻辑结构:数组,栈,队列,字符串,树,图
- 存储结构:顺序存储,链式存储
- 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 0XFFFFtemplate<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