1. 程式人生 > >棧的原理以及實現(基於陣列)

棧的原理以及實現(基於陣列)

棧的定義:

限制僅在表的一端進行插入和刪除運算的線性表。

可以實現“先進後出(或者叫後進先出)”的儲存結構。

棧頂(Top): 允許操作的一端。

棧底(Bottom): 不允許操作的一端。

特點:後進先出。

舉例:物流裝車,先裝車的後出來,後裝車的先出來。

圖片載入中

棧的結構:

空棧:棧頂和棧頂都指向一個無用的頭結點


存有結點的棧:棧頂指標指向棧頂結點,棧底指標指向頭結點


棧的三種實現方案:靜態陣列、動態分配的陣列、動態分配的鏈式結構。

靜態陣列:長度固定,在編譯時確定。優點:結構簡單,實現方便。缺點:不夠靈活、適用於知道明確長度的場合。

動態陣列:長度可在執行的時才確定,並且可以更改原來陣列的長度。優點:靈活。缺點:會因此增加程式的複雜性。

鏈式結構:無長度上限。需要的時候再申請分配記憶體空間。優點:最靈活。缺點:鏈式結構的連結欄位需要消耗一定記憶體;在鏈式結構中訪問特定元素效率不如陣列。

棧的三種實現

首先確定一個棧介面的標頭檔案,裡面包含了各個實現方案下的函式原型,放在一起是為了實現程式的模組化以及便於修改。然後再分別介紹各個方案的具體實現方法。

靜態陣列實現棧:

/* 
**  
** 靜態陣列實現堆疊程式,陣列長度由#define確定 
*/  
  
#include <stack.h>
#include <stdio.h>
#include <assert.h>

#define STACK_SIZE 100 /*棧最大容納元素數量*/

typedef struct Stack{
	SElemType data[STACK_SIZE];  /*棧中的陣列*/
	int top; /*指向棧頂元素的指標*/
}SeqStack;

/*init stack*/
void InitStack(SeqStack *S)
{
	S->top = 0;
}
/*判斷棧是否為空*/
int StackEmpty(SeqStack *S)
{
	if(S->top == 0)
		return 1;
	else
		return 0;
}
/*取棧頂元素*/
int GetTop(SeqStack S, SElemType *e)
{
	if(S->top <= 0){
		printf("當前棧已空\n");
		return 0;
	}
	*e = S.stack[S.top - 1];
	return 1;
}
/*將元素e入棧*/
int push(SeqStack *S, SElemType e)
{
	if(S->top >= StackSize){
		printf("棧滿\n");
		return 0;	
	}
	S->stack[S->top] = e;
	S->top ++;
	return 1;
}
/*將棧頂元素出棧,並賦值給e*/
int PopStack(SeqStack *S, SElemType *e)
{
	if(S->top == 0){
		printf("空棧");	
		return 0;
	}
	S->top --; 
	*e = S->stack[S->top];
	return 1;
}
/*棧的長度*/
int StackLength(SeqStack S){
     return S.top;//儲存著資料的部分是0到top-1,入棧時,如果棧未滿,則在top處存入資料,然後top++
}
/*清空棧*/ 
void ClearStack(SeqStack *S){
     S->top = 0;                    
}
/*判斷棧是否為空*/
int isEmpty(SeqStack *S)
{
	return S->top == 0;
}

/*判斷棧是否滿*/  
int isFull(SeqStack *S)  
{  
    return S->top == StackSize;  
}  
   

動態分配的陣列實現棧:並用棧解決禁止轉換問題:(十進位制轉二進位制或八進位制)

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

#define STACK_INIT_SIZE 10 //定義最初申請的記憶體大小
#define STACK_INCREMENT 2  //每一次申請記憶體不足的時候擴充套件的記憶體大小

#define OVERFLOW 0
#define FALSE 0
#define TRUE 1
#define ERROR 0
#define INFEAIBLE 0 //不可實行的
#define OK 1

typedef int SElemType;
typedef int Status;

int Length;

/*****************結構型別部分******************/
typedef struct Stack
{
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;  //sequence stack順序棧

/*****************構造一個空棧**********************/
Status InitStack(SqStack &S)
{
	if( !( S.base = (SElemType *)malloc( STACK_INIT_SIZE * sizeof(SElemType) ) ) )
		exit(OVERFLOW);  //儲存分配失敗
	
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;  //初始棧容量
	
	return OK;
}

/******************壓入棧元素*********************/
Status Push(SqStack &S, SElemType e)//這裡不是SElemType &e
{
	//棧滿追加記憶體
	if(S.top - S.base >= S.stacksize){
		S.base = (SElemType *) realloc(S.base, sizeof(SElemType) * (S.stacksize + STACK_INCREMENT));
		if(!S.base)
			exit(OVERFLOW);
		//給SqStack的三個物件賦值
		S.top = S.base + S.stacksize;
		S.stacksize += STACK_INCREMENT; 
	}
	*S.top++ = e;//先把e壓入棧頂,S.top再增加1指向棧頂元素e的下一個位置
	return OK;
}
/******************輸出棧元素*********************/
void PrintList(SqStack S)
{
	S.top = S.base;
	for( int i = 0; i< Length; i++){
		printf("%d\n",*(S.top) ++);
	}
}
/******************判斷棧是否為空*****************/
Status StackEmpty(SqStack S)
{
	if(S.base == S.top) return true;
	else return false;
}
/******************刪除棧頂元素*******************/
Status Pop(SqStack &S, SElemType &e)
{
	//判斷是否為空
	if( S.base == S.top ) return ERROR;
	
	e = *--S.top;
	return OK;
}

/********************進位制轉換********************/
int conversion(unsigned int n,unsigned int m)//十進位制數轉化成m進位制
{
	SqStack s;
	InitStack(s);
	int e = 0;

	unsigned result = 0;
	while(n)
	{
		Push(s, (SElemType)n%m);
		n /= m;
	}
	while( !StackEmpty(s))
	{
		Pop(s,e);
		result = result*10 + e;
	}
	return result;
} 

int main()
{
	int n = 123;
	int m = 2;
	int result = conversion(n,m);
	printf("%d\n", result);
	return 0;
}