棧(stack) C語言實現 詳解


棧是數據結構中較為簡單的結構體,是一種操作收到限制的線性表.但簡單不代表沒用,畢竟數組很簡單.但誰敢說數組沒用呢?

棧的理論

  • 棧是一個先進后出的結構,類似於堆盤子,先放到地上的盤子最后被取走(默認只能取走一個盤子)
  • 棧其實就是操作受限的線性表,只有一個口,每一次操作時,這個口可以當出口也可以當入口.
  • 例如:水桶,注入水時,水桶的頭當做入口,倒水時,水桶的頭當做出口

棧的圖解.

在圖解之前,先舉一個例子,讓大家記住棧:
棧其實就是吃了一頓飯,然后吐出來.

  • 1. 這是一個空棧,只有上面是入口和出口
    一個空棧
  • 放入一個元素a
    放入一個元素a
  • 放入一個元素b
  • 放入一個元素c
    分別放入一個元素b和c
  • 取出一個元素,由棧只有一個口的特點可以知道取出了C
    這里寫圖片描述
  • 再次放入一個元素d
    放入元素d

由圖可以得到:無論是入,還是出,都只有一個口,一個口擔當兩個作用.

棧的可用操作

根據理論環節,可以輕易的看出:棧的基本操作只有兩個:

  • 入棧
  • 出棧
    但是如果棧已經放滿了,就像水桶裝滿了水一樣,不能再放水了,即不能再進行入棧操作,所以要在每次入棧前判斷棧滿的情況.
    同理,出棧之前,棧中必須有數據,不然就出現要么空指針,要么野指針.都不是我們想要的結果,所以出棧前要判斷棧空,.
    所有一個棧一共有四個功能:

-入棧(英文名:push)
-判(棧)滿(isFull)
-出棧(pop)
-判(棧)空(isEmpty)

棧的C語言定義(結構體)

開篇就說了棧是操作收到限制的線性表,而眾所周知的線性表主要有:
1.順序存儲的數組,
優點: 節省空間, 操作簡單,學習成本較低,易於理解.
缺點: 棧的大小一開始就聲明’死’了,不利於使用.
2.非順序存儲的鏈表.
優缺點:與數組棧正好相反.

  • 兩種棧各有好處,爭論是愚蠢的,學習是學不完的,所以趕快開始coding吧

數組棧

  • 數組棧,顧名思義,就是基於數組的棧,也是說把一個數組的強大的下標功能閹割掉,並且只能從一頭進入(數組頭明顯更為方便)
    所以結構體為:
    (為了方便學習,存儲類型統一使用int,但是我們一般更習慣在頭文件下面給int 起一個別名,原因很簡單:這樣就這樣實現簡單的多態,需要將int類型棧改成char類型棧時,只需要改定義的別名中的類型即可)
typedef struct
{
    int Data[MaxSize];   // 存儲元素的數組
    intTop;       //棧頂指針
}SeqStack;
  • 棧的四個基本操作定義
//return 0 為false,1為true(下同)
int Push(SeqStack &L)
{
    if(L.Top == 0)
    {
        return 0;
    }
    printf("%d ",L.Data[--L.Top]);
    return 1;
}
int Pop(SeqStack &L, int e)
{
    if(L.Top==MaxSize -1)
    {
        return 0;
    }
    L.Data[L.Top++] = e;
    return 1;
}
//判斷棧s是否為空
int isEmpty(SeqStack s)
{
    if(s.Top != 0)
    {
        return 1;
    }
    return 0;
}
Status isFull(SeqStack s)
{
    if(s.Top != MaxSize -1)//之前的定義數組的最大值的下標
    {
        return 1;
    }
    return 0;
}

鏈表棧

結構體

typedef struct LNode
{
    ElemType data;
    struct LNode * next;
} LNode,*LinkList;

兩大功能(鏈表無需判滿,判空也簡單,不再單獨實現)

Status Push(LinkList L)
{
    if(L->next == NULL)
    {
        return 0;
    }
    LinkList tem = L->next;
    printf("%d ",tem->data);
    L->next = tem->next;
    free(tem);
    return 1;
}
Status Pop(LinkList L, ElemType e)
{
    LinkList newNode = (LinkList) malloc(sizeof(LinkList));
    newNode->data = e;
    newNode->next = L->next;
    L->next = newNode;
    return 1;
}

最后寫幾個簡單的作業(我們老師留給我們的)以及我的代碼

//1、本題要求實現順序棧,寫出Push 、Pop、StackEmpty函數的實現,並用一個簡單的main函數測試。

//已有類型定義
typedef struct
{
    ElementType Data[MaxSize];   // 存儲元素的數組
    Position Top;       //棧頂指針
}SeqStack;

//函數接口定義:
Status Push(SeqStack &L, ElemType e);
Status Pop(SeqStack &L, ElemType &e);
Status StackEmpty(SeqStack s);  //判斷棧s是否為空
//其中 L 和 e 都是用戶傳入的參數。 L 是帶頭結點的頭指針; e 是數據元素。
/** * 3、進制轉換。 * 輸入一個十進制正整數n和一個目標進制R(1<R<10),將n轉換為R進制。要求不使用遞歸或數組,而使用第1題或第2題中定義的棧來實現。 */ 

代碼:

#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef int Status;
typedef int ElemType;
typedef int Position;
//1、本題要求實現順序棧,寫出Push 、Pop、StackEmpty函數的實現,並用一個簡單的main函數測試。
//已有類型定義
typedef struct
{
    ElemType Data[MaxSize];   // 存儲元素的數組
    Position Top;       //棧頂指針
} SeqStack;

//函數接口定義:
Status Push(SeqStack &L);
Status Pop(SeqStack &L, ElemType e);
Status StackEmpty(SeqStack s);  //判斷棧s是否為空
Status prinStack(SeqStack &L);
Status convNum(int n, int R);
Status pipei();
void work1();
//其中 L 和 e 都是用戶傳入的參數。 L 是帶頭結點的頭指針; e 是數據元素。
int main()
{
    //work1();//第一題
    //convNum(8,2);//進制轉化
    pipei();
    return 0;
}
Status prinStack(SeqStack &L)
{
    while (StackEmpty(L))
    {
        Push(L);
    }
    return 1;
}
void work1()
{
    SeqStack L;
    L.Top = 0;
    Pop(L, 1);
    Pop(L, 2);
    Pop(L, 3);
    prinStack(L);
}
Status Push(SeqStack &L)
{
    if(L.Top == 0)
    {
        return 0;
    }
    printf("%d ",L.Data[--L.Top]);
    return 1;
}
Status Pop(SeqStack &L, ElemType e)
{
    if(L.Top==MaxSize -1)
    {
        return 0;
    }
    L.Data[L.Top++] = e;
    return 1;
}
//判斷棧s是否為空
Status StackEmpty(SeqStack s)
{
    if(s.Top != 0)
    {
        return 1;
    }
    return 0;
}
//3、進制轉換。
//輸入一個十進制正整數n和一個目標進制R(1<R<10),將n轉換為R進制。要求不使用遞歸或數組,而使用第1題或第2題中定義的棧來實現。
Status convNum(int n, int R)
{
    //聲明棧
    SeqStack L;
    L.Top = 0;
    while (n!=0)
    {
        //將每次產生的余數防入棧低
        Pop(L, n%R);
        n/=R;
    }
    prinStack(L);
    return 1;
}

以下附上Java 代碼實現的棧


/** * Description: 鏈表實現棧。 * * @ClassName: LinkedStack * @author 過道 * @date 2018年8月10日 下午9:11:30 * @version V1.0 * */
public class LinkedStack<T> implements StackInterface<T> {
    private Node topNode;

    @Override
    public void push(T newEntry) {
        Node newNode = new Node<T>(newEntry, topNode);
        topNode = newNode;
    }

    @Override
    public T pop() {
        T tempData = peek();
        if (tempData == null) {
            return null;
        }
        topNode = topNode.next;
        return tempData;
    }

    @Override
    public T peek() {
        if (isEmpty()) {
            return null;
        }
        return (T) topNode.data;
    }

    @Override
    public boolean isEmpty() {
        return topNode == null;
    }

    @Override
    public void clear() {
        topNode = null;
        // java擁有內存回收,只需要讓頭結點引用為空即可,GC就可以回收掉所有其他節點。
    }

    public LinkedStack() {
        this.topNode = null;
    }

    private class Node<T> {
        private T data;
        private Node next;

        public Node(T dataPortion) {
            this(dataPortion, null);
        }

        public Node(T data, Node next) {
            super();
            this.data = data;
            this.next = next;
        }

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }

        public Node getNext() {
            return next;
        }

        public void setNext(Node next) {
            this.next = next;
        }

    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM