栈和队列

来源:互联网 发布:java的equals方法 编辑:程序博客网 时间:2024/06/13 07:25


1.栈

(1)后进先出;
         实现:栈顶指针指向栈顶元素,插入时先修改指针再插入,删除时先取栈顶元素再修改指针;
         栈顶元素S[S.top],栈底元素S[1];
         只能在栈顶上插入和删除;
(2)栈数据结构(用vector实现也行,更简单):
         int top;    //栈顶指针
         int stackLen;//栈长度
         int *data;//指向栈数组
(3)在栈上实现的操作:
         STACK-EMPTY(S)//判断栈是否为空
         PUSH(S, x)            //把x压入到栈顶
         POP(S)                 //取出并返回栈顶元素
 下面是实现代码:
/*栈的实现:数组为基础数据结构*/class Stack{private:int top;//栈顶指针int dataLen;//栈数组大小int *data;Stack(){}public:Stack(int stackSize){dataLen = stackSize;top = -1;data = new int[stackSize];}~Stack(){delete []data;}bool IsEmpty();int Pop();void Push(int x);void printStack();};bool Stack::IsEmpty(){return top<0 ;}void Stack::Push(int x){if(top>=dataLen-1){cerr<<"栈上溢!"<<endl;return;}data[top+1] = x;top++;}int Stack::Pop(){if(top<0){cerr<<"栈下溢!"<<endl;return INT_MIN;}int val = data[top];top--;return val;}void Stack::printStack(){//---栈底到栈顶顺序输出for(int i=0 ; i<dataLen ; i++)cout<<data[i]<<" ";cout<<endl;}

补充说明:

       1.最先进栈的元素是不是就只能是最后出栈呢?
       答:不一定,栈只是对入栈出栈的位置作了限制,并没有对元素的进出时间进行限制。如1、2、3依次进栈,可能的出栈顺序有:
             1进1出2进2出3进3出---123序;1进1出2进3进3出2出---132序;1进2进2出1出3进3出---213序;1进2进3进3出2出1出---321序;1进2进2出3进3出1出---231序。最先进栈的元素1可以最先出栈,出栈顺序与时间无关的。

       2.双向栈:两栈共享存储空间(数组),前提是对于两个栈中数据类型相同,可以让栈A栈顶从0开始,栈B栈顶从M-1开始。于是二者的判空条件分别为topA==-1与topB==M;判满条件是topA+1==topB。代码很简单,不需要作过多讲解。Push与Pop的时候用一个标志位进行标记是对哪个栈进行操作即可。

/*双向栈的实现*/typedef int ElemType;#define MAXSIZE 100struct SqDoubleStack{SqDoubleStack():topA(-1),topB(MAXSIZE){}ElemType data[MAXSIZE];int topA;int topB;bool Push(ElemType e , int stackNumber);bool Pop(ElemType *e , int stackNumber);void printStack(int stackNumber);};bool SqDoubleStack::Push(ElemType e , int stackNumber){if(topA+1 == topB)       //栈已满,不能再push新元素了return false;if(stackNumber == 1)           //栈A有元素进栈data[++topA] = e;    //若栈1则先top+1后给数组元素赋值else if(stackNumber == 2)      //栈B有元素进栈data[--topB] = e;    //若栈2则先top2-1后给数组元素赋值return true;}//若栈不空,则删除s的栈顶元素,用e返回其值,并返回OK;否则返回ERRORbool SqDoubleStack::Pop(ElemType *e , int stackNumber){if(stackNumber == 1){if(topA == 1)return false;            //说明栈1已经是空栈,溢出*e = data[topA--];     //将栈1的栈顶元素出栈 }else if(stackNumber == 2){if(topB == MAXSIZE)return false;            //说明栈2已经是空栈,溢出*e = data[topB++];     //将栈2的栈顶元素出栈}return true;}//---由栈底到栈顶打印元素void SqDoubleStack::printStack(int stackNumber){if(stackNumber == 1){if(topA == 1)//栈A是空栈return;for(int i=0 ; i<=topA ; i++)cout<<data[i]<<" ";cout<<endl;}else if(stackNumber == 2){if(topB == MAXSIZE)//栈B是空栈return ;            for(int i=MAXSIZE-1 ; i>=topB ; i--)cout<<data[i]<<" ";cout<<endl;}}int main(){SqDoubleStack stack;for(int i=0 ; i<9 ; i++)stack.Push(i+1,1);for(int i=0 ; i<9 ; i++)stack.Push(i+1,2);stack.printStack(1);stack.printStack(2);return 0;}
       3.栈的链式存储结构:
        由于链栈的栈顶可以作为链表的头结点,因此链栈不需要头结点。链栈基本不存在栈满的情况,除非内存已经没有可用的空间,如果真是如此操作系统已近面临死机崩溃的问题,而不是链栈是否溢出的问题。链栈判空条件就是top==NULL,链栈绝大部分操作都与单链表类似,只在插入和删除上特殊一些。

/*链栈的实现*/typedef int ElementType;struct StackNode{StackNode():next(NULL){}ElementType data;StackNode *next;};class LinkStack{private:StackNode* top;//栈顶指针int count;//链栈内元素个数void destory();//释放链栈申请内存public:LinkStack():top(NULL){}~LinkStack();bool Push(ElementType e);bool Pop(ElementType *e);bool StackEmpty();void printLinkStack();};LinkStack::~LinkStack(){destory();top = NULL;}bool LinkStack::StackEmpty(){return (NULL == top);}void LinkStack::destory(){StackNode *p = top;StackNode *t;while(p){t = p;p = p->next;delete t;t = NULL;}}bool LinkStack::Push(ElementType e){//---无需判满StackNode* t = new StackNode;t->data = e;t->next = top;top = t;count++;return true;}bool LinkStack::Pop(ElementType *e){if(StackEmpty())//空栈return false;*e = top->data;StackNode *t = top;top = top->next;delete t;count--;return true;}//---从顶到底打印元素void LinkStack::printLinkStack(){if(StackEmpty())//空栈return;StackNode *p = top;while(p){cout<<p->data<<" ";p = p->next;}cout<<endl;}int main(){LinkStack stack;for(int i=0 ; i<9 ; i++)stack.Push(i+1);stack.printLinkStack();return 0;}

2.队列

 (1)先进先出;
          实现:队列的头指针指向队列首元素,删除时先取队列首元素再修改指针,队列的尾指针指向队尾元素的下一个元素,插入时先插入再修改指针;
          队头元素Q[head],队尾Q[tail];
          只能在队头出队,队尾入队。
(2)数组队列的结构:
          int tail;      //队尾,指向最新进入的元素
          int head;  //队头,指向最先出的元素
          int length;//队列的长度
          int *data; //指向队列数组
(3)在队列上实现的操作:
          ENQUEUE(Q, x)            //把x插入到队列尾
          DEQUEUE(Q)                //取出队列首元素并返回
    说明:1.对于数组实现的队列,可能会出现“假溢出”的情况,于是常常实现为循环队列,对于循环队列有两种判定是否为空可以用flag==0&&front==rear,为满可以用flag==1&&front==rear;还可以预留一个空位,如果为空rear==front,为满(rear+1)%QueueSize==front。
               2.对于队列自然也有链队列,此时对头指针指向链队列的头结点队尾指针指向终端节点。
/*链队列的实现*///链式队列的结点类型定义typedef int ElemType;struct QNode{QNode():next(NULL){}ElemType data;                 QNode *next;                 };//链式队列class LinkQueue{private:QNode*  front;                QNode*  rear;public:LinkQueue():front(NULL),rear(NULL){QNode *t = new QNode;front = rear = t;front->next = rear->next = NULL;}~LinkQueue(){while(front){rear = front->next;delete(front);front = rear;}}int QueueLength();void EnQueue(ElemType e);bool DeQueue(ElemType &e);};//求队列的长度int LinkQueue::QueueLength(){QNode *p = front;    //p指向头结点int count = 0;while (p->next != NULL){count++;p = p->next;}return count;}//队尾入队void LinkQueue::EnQueue(ElemType e){ QNode *p = new QNode;if(!p)exit(OVERFLOW);p->data = e;p->next=NULL;  //生成一个数据为X的结点rear ->next = p ;    //将结点P插入队尾rear = p;          //修改队尾指针,令其指向P结点}//队首(头结点的后继)出队bool LinkQueue::DeQueue(ElemType &e) {//链队列Q为空if(front->next = NULL) return false;QNode* p = front->next; //令p指向队列Q的第一个有效节点 e = p->data;             front->next =  p->next;//修改队头指针if(rear == p) //被删除的是队尾结点,修改rear为frontrear = front;  delete p;return true;}
下面是普通队列的实现代码:
/*队列的实现:数组为基础数据结构*/class Queue{public:Queue(){}Queue(int QSize):dataLen(QSize),front(0),rear(0){data = new int[QSize];}~Queue(){delete []data;}void printQueue();void EnQueue(int x);int DeQueue();bool isEmpty();bool isFull();private:int *data;int dataLen;//有效数据为dataLen-1,留空作为判空和判满标识int front;//对头指针,指向第一个有效元素位置int rear;//队尾指针,最后一个有效元素的下一个位置};bool Queue::isEmpty(){return front==rear;}bool Queue::isFull(){return (rear+1)%dataLen==front;}//从头到尾输出元素void Queue::printQueue(){if (isEmpty()){cout<<"队列已空!"<<endl;return;}if(front<rear){//对头在队尾前面for(int i=front ; i<rear ; i++)cout<<data[i]<<" ";cout<<endl;}else{//对尾在队头前面for(int i=front ; i<=dataLen-1 ; i++)cout<<data[i]<<" ";for(int i=0 ; i<rear ; i++)cout<<data[i]<<" ";cout<<endl;}}void Queue::EnQueue(int x){if(isFull()){cout<<"队列已满!"<<endl;return;}data[rear] = x;if(rear == dataLen-1)//队尾指向最后位置rear = 0;//循环数组elserear++;}int Queue::DeQueue(){if(isEmpty()){cout<<"队列已空!"<<endl;return INT_MIN;}int val = data[front];if(front == dataLen-1)//对头指向最后位置front = 0;elsefront++;return val;}
0 0
原创粉丝点击