數據結構與算法之隊列、棧

jopen 9年前發布 | 13K 次閱讀 算法

 

除了數組、鏈表,線性的數據結構中還有很重要的幾種結構: 隊列、棧

隊列,一種先進先出的數據結構(FIFO),其實隊列可以看成是一個兩個口的管道,從一個口進,另一個口出,先進去的必定得在另一個口先出去,否則后面的都出不去;棧,一種后進先出的數據結構(LIFO),棧更像是只有一個口的管道,只有一個開口可以進出,先進去的在底部,所以必須得讓后進去的先出去,它才能出去。

實現隊列和棧可以用順序存儲結構,也可以用鏈式存儲結構。這里采用的是鏈表來實現,同時還有用兩個棧實現一個隊列和用兩個隊列實現一個棧的算法(采用STL中的queue和stack)。

1、隊列

隊列中最常用的操作就是入隊列(push),出隊列(pop),查看隊首的值(front)。入隊列是加入隊列的尾部,出隊列是刪除最前面的節點。

typedef struct ListNode{
  int element;
  int *next;
}ListNode;
typedef struct LinkedQueue{
  int size;
  ListNode *front;
  ListNode *back;
}LinkedQueue;
/* alloc a node.*/
ListNode* allocNode(int element){
  ListNode *pNode = (ListNode*)malloc(sizeof(ListNode));
  if(pNode){
    pNode->element = elemnt;
    pNode->next = NULL;
  }
  return pNode;
}
/* alloc a queue.*/
LinkedQueue* allocLinkedQueue(){
  LinkedQueue *pQueue = (LinkedQueue*)malloc(sizeof(LinkedQueue));
  if(pQueue){
    pQueue->size = 0;
    pQueue->front = NULL;
    pQueue->back = NULL;
  }
  return pQueue;
}
/* pop a node out of the queue.*/
bool pop(LinkedQueue *pQueue){
  if(NULL == pQueue)
     return false;
  LinkedQueue *pNode = pQueue->front;
  if(pQueue->front == pQueue->back)
    pQueue->back = NULL;
  pQueue->front = pQueue->front->next;
  free(pNode);
  pQueue->size --;
  return true;
}
/* push a node into the queue.*/
bool push(LinkedQueue *pQueue,int element){
  if(NULL == pQueue)
    return false;
  pQueue->size ++;
  if(NULL == pQueue->front){
    pQueue->front = pQueue->back = allocNode(element);
  }
  else
    pQueue->back = allocNode(element);
  return true;
}
/* get the front element from the queue.*/
bool front(LinkedQueue *pQueue,int *element){
  if(pQueue->size){
    *element = pQueue->front->element;
    return true;
  }
  else
    return false;
}

2、棧

棧中最常用的操作就是入棧(push),出棧(pop),查看棧頂的值(front)。入棧是加入棧的頂部,出棧刪除棧頂的節點。

typedef struct ListNode{
  int element;
  struct ListNode *next;
}ListNode;
typedef struct LinkedStack{
  ListNode *topNode;
  ListNode *downNode;
  int stackLength;
}LinkedStack;
/* get the top node from the stack.*/
int top(LinkedStack *pStack){
   return pStack->topNode->element; 
}
/* pop the top node from the stack.*/
void pop(LinkedStack **pStack){
  ListNode *pNode = (*pStack)->topNode->next;
  free(*pStack);
  *pStack = pNode;
}
ListNode* allocNode(int element){
  ListNode *pNode = (ListNode*)malloc(sizeof(ListNode));
  if(NULL != pNode){
    pNode->element = element;
    pNode->next = NULL;
  }
  return pNode;
}
/* push a node into the stack.*/
void push(LinkedStack **pStack,int element){
  ListNode *pNode = allocNode(element);
  pNode->next = (*pStack)->topNode;
  (*pStack)->topNode = pNode;
}

3、用兩個棧實現一個隊列

隊列是先進先出,而棧是后進先出,怎么在棧中實現讓一個元素先進先出?關鍵是利用好另一個棧。隊列中主要的操作也不過就是push(),pop(),front()。

實現push就跟棧中的push一樣,完全不需要修改。而要實現pop和front呢?這就需要借助另一個棧。首先在棧stack1中 push,當有pop或者front操作時,我們把元素從stack1中出棧并壓入stack2中。這樣stack1中底部的元素就變為stack2頂部的元素了,然后從stack2中執行pop或者front操作。以后的pop或者front操作,都先從stack2中執行,當stack2中元素 size為0時,就從stack1中出棧并壓入stack2中然后執行;而每次pop操作只需要在stack1中執行。

bool pop(){
  if(!pQueue.stack2.size() && !pQueue.stack1.size())
    return false;
  if(!pQueue.stack2.size()){
    while(pQueue.stack1.size()){
      pQueue.stack2.push(pQueue.stack1.top());
      pQueue.stack1.pop();
    }
  }
  pQueue.stack2.pop();
  return true;
}
int front(){
  if(!pQueue.stack2.size()){
    while(pQueue.stack1.size()){
      pQueue.stack2.push(pQueue.stack1.top());
      pQueue.stack1.pop();
    }
  }
  return pQueue.stack2.top();
} 

4、用兩個隊列實現一個棧

棧中最主要的操作就是push(),pop(),top()。

push操作每次把元素加入到queue1中即可,而pop和top操作就需要借助另一個隊列了。假設queue1中壓入了5個元素:1,2,3,4,5。則此時需要pop,也就是刪除元素5。那么現在就需要把元素1,2,3,4pop了,才能pop元素5,但是棧操作中元素 1,2,3,4不應該被pop掉,所以,就需要把1,2,3,4push到queue2中。每次pop操作,就先檢查queue1中是否有元素,如果有n 個元素,就把前面的n-1個元素pop,然后push到queue2中,然后執行pop;否則,就先把queue2中的n-1元素轉移到queue1中,然后執行pop操作。top操作與pop操作類似。

bool pop(){
  if(!pStack.queue1.size() && !pStack.queue2.size())
    return false;
  if(pStack.queue1.size())  {
    while(pStack.queue1.size() != 1){
      pStack.queue2.push(pStack.queue1.front());
      pStack.queue1.pop();
    }
    pStack.queue1.pop();
    return true;
  }
  else{
    while(pStack.queue2.size() != 1){
      pStack.queue1.push(pStack.queue2.front());
      pStack.queue2.pop();
    }
    pStack.queue2.pop();
    return true;
  }
}
int top(){
  if(pStack.queue1.size())  {
    while(pStack.queue1.size() != 1){
      pStack.queue2.push(pStack.queue1.front());
      pStack.queue1.pop();
    }
    return pStack.queue1.front();
  }
  else{
    while(pStack.queue2.size() != 1){
      pStack.queue1.push(pStack.queue2.front());
      pStack.queue2.pop();
    }
    int top = pStack.queue2.front();
    pStack.queue2.pop()
    pStack.queue1.push(top);
    return top;
  }
}

完整代碼詳見: https://github.com/whc2uestc/DataStructure-Algorithm

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!