1. 程式人生 > >資料結構---堆疊

資料結構---堆疊

簡單介紹堆疊(特點:先進後出)的基本運算

#include <stdio.h>
#include <stdlib.h>
#define maxsize 1000

typedef struct //順序棧結構
{
    int data[maxsize];
    int top;
}SeqStack;

SeqStack *Init_SeqStack()//置空順序棧
{
    SeqStack *s;
    s=(SeqStack*)malloc(sizeof(SeqStack));
    s->top=-1;
    return s;
}

int Empty_SeqStack(SeqStack *s)//判斷棧是否空
{
    if(s->top==-1)return 1;
    else return 0;
}

int Push_SeqStack (SeqStack *s,int x)//入棧
{
    if(s->top==maxsize-1)return 0;//判斷棧滿,若棧滿,不可入棧,否則會空間溢位
    else
    {
        s->top++;
        s->data[s->top]=x;
        return 1;
    }
}

int Pop_SeqStack(SeqStack *s,int *x)//出棧,地址傳遞,防資料丟失
{
    if(s->top==-1)return 0;//判斷棧空,可出棧
    else
    {
        *x=s->data[s->top];//儲存下移前棧頂資料,用指標地址傳遞
        s->top--;//棧頂位置下移
        reutrn 1;
    }
}

int Top_SeqStack(SeqStack *s,int *x)//取棧頂元素
{
    if(s->top==-1)return 0;
    else
    {
        *x=*x=s->data[s->top];
        return 1;
    }
}

鏈棧的基本操作有判棧空和入棧,相對順序棧用的較少

typedef struct snode//鏈棧結構
{
    int data;
    struct snode *next;
}StackNode,*LinkStack;

LinkStack *top;//定義棧頂指標變數
int Empty_LinkStack(LinkStack top)
{
    if(top==NULL)return 1;
    else return 0;
}

LinkStack Push_LinkStack(LinkStack top,int x)//入棧
{
    StackNode *p;
    p=(SeqStack*)malloc(sizeof(SeqStack));
    p->data=x;
    p->next=top;
    top=top->next;
    top=p;
}

堆疊的應用例項(運用堆疊“先進後出”的特點)

數制轉換問題

將十進位制數N轉換為r進位制數,其轉換方法利用輾轉相除法

void conversionn(int N,int r)//呼叫棧的基本操作實現數制轉換
{
    SeqStack *s;
    int x;
    s=Init_SeqStack();
    while(N!=0)
    {
        Push_SeqStack(SeqStack *s,N%r);
        N=N/r;
    }
    if(!Empty_SeqStack(s))
    {
        Pop_SeqStack(SeqStack *s,&x);
        printf("%d",x);
    }
}
void conversionn(int N,int r)//自定義順序棧實現數制轉換
{
    int S[maxsize],top=-1;//定義一個順序棧並初始化
    int x;
    while(N!=0)
    {
        S[++top]=N%r;//餘數入棧
        N=N/r;//商作為被除數繼續
    } 
    while(top!=-1)   
    {
        x=S[top--];
        printf("%d",x);
    }
}

 利用棧實現迷宮問題

這是實驗心理學的一個有名實驗,我們採取回溯法解決該問題。

    (1)設迷宮為m行,n列,將迷宮看成一個maze[m][n]的陣列,maze[i][j]=0表示可走,maze[i][j]=1表示不可走,中間的點有八個方向可走,四角則一個方向,四邊有五個方向,為使問題簡化,我們可把迷宮看成m+2行,n+2列,則所有點都有八個方向可選擇,新增四周均設1不可走,與迷宮四周都是牆相一致。

    (2)八個方向我們用含資料x,y的結構move表示,由x軸正方向為開始,順時針進行這八個方向的試探

    (3)到達新點我們還需要一個方向序號d表示,若無路可走我們需返回到前一點

    (4)為避免到達重複點而進入死迴圈,我們將到達的點進行標記,置maze[i][j]=-1

下面為核心部分演算法

#define m 6
#define n 8
typedef struct //移動結構
{
    int x;
    int y;
}item;
typedef struct //移動結構
{
    int x;
    int y;
    int d;
}data;
item move[8]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
int path(int maze[m+2][n+2],item move[8])
{
    SeqStack *s;
    data temp;
    int x,y,d,i,j;int tempx,tempy,tempd;
    temp.x=1;temp.y=1;temp.d=-1;
    Push_SeqStack(s,temp);//入口進棧
    while(!Empty_SeqStack(s))
    {
        Pop_SeqStack(s,&temp);
        x=temp.x;y=temp.y;d=temp.d+1;//回到上一座標位置進行下一座標試探
        while(d<8)//當還有方向可試
        {
            i=x+move[d].x;j=y+move[d].y;//新點座標
            if(maze[i][j]==0)
            {
                tempx=x;tempy=y;tempd=d;//記錄當前座標及位置
                Push_SeqStack(s,temp);
                x=i;y=j;maze[x][y]=-1;//到達新點
                if(x==m&&y==n)return 1;//是出口則迷宮有路
                else d=0;//不是出口繼續試探
            }
            else  d++;
        }
    }
    return 0;
}