數據結構:棧(linked-stack & array-stack)

棧是一種特別的線性表。在棧中,只能在數據的一端(即棧頂)進行操作。最經典的解釋這個策略的例子就是疊盤子。盤子只能一個一個不斷放在之前的盤子堆上,拿盤子的時候也只能從上往下一個一個拿。這兩個操作,在stack中分別對於push和pop,即壓棧和出棧。這體現了棧的後進先出(LIFO)特性。

棧

壓棧(push)

出棧(pop)

2. 棧的實現

stack的實現分爲兩種,一種是使用數組來模擬棧,另外一種是使用鏈表來模擬棧。

2 .1 數組實現(array stack)

首先,先來看使用數組的方法。


棧的結構爲
#define MAX_SIZE 20 //棧內最多有幾個元素
typedef int StackEntry;
typedef struct stack {
      StackEntry entry[MAX_SIZE];
      int top; 
} Stack ;

用數組實現的棧使用連續的內存地址,爲了能夠知道棧頂位置,需要使用一個變量標記。

看起來,數組的實現方式十分的簡單!So easy!當向棧中壓入數據時,需要將top的值加1;出棧時,top的值減1。Too young,too naive!考慮兩個極端的情況:在棧滿時壓棧,在棧空時出棧。因此在進行push和pop操作之前需要檢查棧的情況,避免溢出。

 int IsFull(Stack *s) {
    return (s->top >= MAX_SIZE);
 }

 int IsEmpty(Stack *s) {
    return (s->top <= 0);
 }

void Push(StackEntry item, Stack* s) {
  if(IsFull(s))
    return;
  else
    s->entry[s->top++] = item;
}

void Pop(Stack* s) {
   if(IsEmpty(s))
      return;
   else
      s->top--;
}

StackEntry Top(Stack* s) {
   if(!IsEmpty(s))
      return s->entry[s->top-1];
   else 
      return -1;
}

2.2. 鏈式實現(linked stack)

鏈式棧使用鏈表的存儲形式實現,其存儲是不連續的。我們首先定義stack的結構如下:

typedef struct node {
  StackEntry val;
  struct node *next;
} Node;

一般來說,很多人會自然而然的想到在stack中將心的元素加入到linked stack的末尾。但是要考慮到,對於stack,我們經常在其末尾進行操作,如果將元素插入到link的末尾,那麼每次操作都要先從頭到達末尾才能操作,所以我們需要換另外一種方法,採用前插的方式,將新的元素插入到列表的前面。這樣每次進行push和pop操作的時候就可以直接通過top指針操作。

後插

前插


//push a new node onto the top of the stack (the front of the list),
//and return whether successful
int Push (int val, Node* stack) {

    Node* addNode = (Node*)malloc(sizeof(Node));

    if (addNode == NULL) {
        printf("out of memory!\n");
        return 0;
    }

    addNode->val = val;
    addNode->next = stack->next;
    stack->next = addNode;

    return 1;
}


//pop the top node from the stack
int Pop (Node* stack) {

    if (IsEmpty(stack)) {
        printf("the stack is empty!\n");
        return 0;
    }

    Node *tmpNode = stack->next;
    stack->next = tmpNode->next;
    free(tmpNode);

    return 1;
}


//check whether the stack is empty
int IsEmpty (Node* stack) {

    return (stack->next == NULL);
}


//get the top value of the stack
int Top (Node* stack) {

    if (IsEmpty(stack)) {
        printf("the stack is empty!\n");
        return -1;
    }

    return (stack->next->val);
}

綜合所有操作

數組實現

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 20 //棧內最多有幾個元素

typedef int StackEntry;
typedef struct stack {
      StackEntry entry[MAX_SIZE];
      int top;
} Stack;

int IsFull(Stack *s) {
    return (s->top >= MAX_SIZE);
 }

int IsEmpty(Stack *s) {
    return (s->top <= 0);
 }

void Push(StackEntry item, Stack* s) {
  if (IsFull(s))
    return;
  else
    s->entry[s->top++] = item;
}

void Pop(Stack* s) {
   if (IsEmpty(s))
      return;
   else
      s->top--;
}

StackEntry Top(Stack* s) {
   if (!IsEmpty(s))
      return s->entry[s->top-1];
        else
            return -1;
}

int main () {

    Stack *s = (Stack*)malloc(sizeof(Stack));
    s->top = 0;

    Push(1, s);

    Push(2, s);

    Push(3, s);

    //get 3
    int temp = Top(s);
    printf("%d ", temp);

    //pop 3
    Pop(s);
    temp = Top(s);
    printf("%d ", temp);

    Push(4, s);
    temp = Top(s);
    printf("%d ", temp);

    //pop 4
    Pop(s);
    temp = Top(s); // top is 2
    printf("%d ", temp);

    //pop 2
    Pop(s);
    temp = Top(s); //top is 1
    printf("%d ", temp);

    //pop 1
    Pop(s);
    temp = Top(s); //error get top element from empty stack
    printf("%d ", temp);

    return 0;
}

輸出:3 2 4 2 1 -1

鏈式實現

#include <stdio.h>
#include <stdlib.h>


typedef struct node
{
    int val;
    struct node *next;
} Node;


Node* CreateEmptyStack ();
int Push (int val, Node* stack);
int Pop (Node* stack);
int IsEmpty (Node* stack);
int Top (Node* stack);


int main () {

    Node *s = CreateEmptyStack();

    Push(1, s);

    Push(2, s);

    Push(3, s);

    int temp = Top(s); //top is 3
    printf("%d ", temp);

    Pop(s); //pop 3
    temp = Top(s); //top is 2
    printf("%d ", temp);

    Push(4, s);
    temp = Top(s); //top is 4
    printf("%d ", temp);

    Pop(s); //pop 4
    temp = Top(s); //top is 2
    printf("%d ", temp);

    Pop(s); //pop 2
    temp = Top(s); //top is 1
    printf("%d ", temp);

    Pop(s); //pop 1
    temp = Top(s); //error, get top element from empty stack
    printf("%d ", temp);





    return 0;
}


//create a empty stack and return the address
Node* CreateEmptyStack () {

    Node* stack = (Node*)malloc(sizeof(Node));

    if (stack == NULL) {
        printf("out of memory!\n");
        return NULL;
    }

    stack->val = 0;
    stack->next = NULL;

    return stack;
}


//push a new node onto the top of the stack (the front of the list),
//and return whether successful
int Push (int val, Node* stack) {

    Node* addNode = (Node*)malloc(sizeof(Node));

    if (addNode == NULL) {
        printf("out of memory!\n");
        return 0;
    }

    addNode->val = val;
    addNode->next = stack->next;
    stack->next = addNode;

    return 1;
}


//pop the top node from the stack
int Pop (Node* stack) {

    if (IsEmpty(stack)) {
        printf("the stack is empty!\n");
        return 0;
    }

    Node *tmpNode = stack->next;
    stack->next = tmpNode->next;
    free(tmpNode);

    return 1;
}


//check whether the stack is empty
int IsEmpty (Node* stack) {

    return (stack->next == NULL);
}


//get the top value of the stack
int Top (Node* stack) {

    if (IsEmpty(stack)) {
        printf("the stack is empty!\n");
        return -1;
    }

    return (stack->next->val);
}

輸出:3 2 4 2 1 the stack is empty!
-1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章