1. 程式人生 > >郝斌資料結構入門---P30---棧

郝斌資料結構入門---P30---棧

郝斌資料結構入門---P30---棧

 

線性結構的常見應用之一:棧(只能頭部插入,頭部刪除

定義:一種可以實現“ 先進後出 ”的儲存結構,棧類似於箱子

分類:靜態棧,動態棧

演算法:出棧pop,入棧push(壓棧)

應用:函式呼叫,中斷,表示式求值,記憶體分配,緩衝處理,迷宮

 

為了便於連結串列的操作,產生一個沒有實際含義的頭結點。

 

 

初始化棧init()函式:

建立一個空棧,把pTop和pBotoom都指向頭結點 

 

 

壓棧push()函式:

第一步:先建立一個新的節點
第二步:把val賦給新節點的資料域
第三步:因為每次壓棧到當前棧頂的上方,所以把新節點的指標域指向pTop
第四步:pTop指向新的節點

 

 

遍歷輸出traverse()函式:
定義一個指標p,p永遠指向棧頂元素 
然後從棧頂到棧底依次遍歷 

 

 

出棧pop()函式:
把pS所指向的棧出棧一次,並把出棧的元素存入pVal形參所指向的變數中
如果出棧失敗,返回-1,否則返回1
先定義指標r,然後再把pTop往後移一個,最後把r釋放 

 

 

清空節點clear()函式:
定義兩個指標p和q
p指向棧頂元素,q指向棧頂下一個元素 
這樣釋放p,q剛好是下一個元素,然後再把q賦值給p,q往下移一個 

 

 

程式碼如下:

//動態棧的本質是操作連結串列

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

//NODE  = struct Node
//PNODE = struct Node * 
typedef struct Node
{
	int data;
	struct Node * pNext;
}NODE, *PNODE;


//STACK  = struct Stack
//PSTACK = struct Satck *
//棧裡面有兩個元素pTop,pBottom
typedef struct Stack 
{
	PNODE pTop;		//指向棧的頂部 
	PNODE pBottom;	//指向棧的底部 
}STACK, *PSTACK;	//PSTACK 等價於 struct Stack * 

void init(PSTACK);
void push(PSTACK, int);
void traverse(PSTACK);
int pop(PSTACK, int *);
void clear(PSTACK pS);

int main(void)
{
	STACK S; //STACK 等價於 struct Stack 
	int val; //儲存出棧的元素 
	
	init(&S);//初始化棧,目的是造出一個空棧 
	push(&S, 1);//壓棧 
	push(&S, 2);//壓棧 
	push(&S, 3);//壓棧 
	push(&S, 4);//壓棧 
	push(&S, 5);//壓棧 
	push(&S, 6);//壓棧 
	traverse(&S);//遍歷輸出 
	
	clear(&S);//清空節點 
	traverse(&S);//遍歷輸出 
	
	if (pop(&S, &val))//出棧 
	{
		printf("出棧成功,出棧的元素是%d\n", val);
	}
	else
	{
		printf("出棧失敗!\n");
	}
	
	traverse(&S);//遍歷輸出 
	
	return 0;
}

//初始化目的:建立一個空棧,把pTop和pBotoom都指向頭結點 
void init(PSTACK pS)
{
	pS->pTop = (PNODE)malloc(sizeof(NODE));
	if (NULL == pS->pTop)
	{
		printf("動態記憶體分配失敗!\n");
		exit(-1);
	}
	else
	{
		pS->pBottom = pS->pTop;
		pS->pTop->pNext = NULL;	//pS->pBottom->pNext = NULL;
	}
}

//壓棧 
//第一步:先建立一個新的節點
//第二步:把val賦給新節點的資料域
//第三步:因為每次壓棧到當前棧頂的上方,所以把新節點的指標域指向pTop
//第四步:pTop指向新的節點
void push(PSTACK pS, int val)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));//建立新的節點
	
	pNew->data = val;		//把val賦給新節點的資料域
	pNew->pNext = pS->pTop; //pS->pTop不能改成pS->Bottom 
	pS->pTop = pNew;
	
	return ;
}

//遍歷輸出
//定義一個指標p,p永遠指向棧頂元素 
//然後從棧頂到棧底依次遍歷 
void traverse(PSTACK pS)
{
	PNODE p = pS->pTop;
	
	while (p != pS->pBottom)
	{
		printf("%d ", p->data);
		p = p->pNext;
	}
	printf("\n");
	
	return;
}

//判斷棧是否為空 
int empty(PSTACK pS)
{
	if (pS->pTop == pS->pBottom)
		return 1;
	else
		return 0;
}

//出棧
//把pS所指向的棧出棧一次,並把出棧的元素存入pVal形參所指向的變數中
//如果出棧失敗,返回-1,否則返回1
//先定義指標r,然後再把pTop往後移一個,最後把r釋放 
int pop(PSTACK pS, int *pVal)
{
	if (empty(pS))	//pS本身存放的就是S的地址 
	{
		return 0;
	}
	else//棧是非空 
	{
		PNODE r = pS->pTop;
		*pVal = r->data;//儲存棧頂資料 
		pS->pTop = r->pNext;
		free(r);
		r = NULL;
		
		return 1;
	}
}

//clear 清空節點 
//定義兩個指標p和q
//p指向棧頂元素,q指向棧頂下一個元素 
//這樣釋放p,q剛好是下一個元素,然後再把q賦值給p,q往下移一個 
void clear(PSTACK pS)
{
	if (empty(pS))//空的時候,不需要操作 
	{
		return;
	}
	else //非空的時候,才需要操作 
	{
		PNODE p = pS->pTop;
		PNODE q = NULL;
		
		while (p != pS->pBottom)//不是最後一個元素
		{
			q = p->pNext;
			free(p);
			p = q;
		}
		pS->pTop = pS->pBottom;
	}
}