我們來介紹下堆棧,在開始介紹之前,先區分開兩種數據結構,堆和棧,區別如下
在數據結構中,棧是一種線性表,而且是只可在表的一端進行插入和刪除運算的線性表;而堆是一種樹形結構,其滿中樹中任一非葉結點的關鍵字均不大於或不小於其左右子樹的結點的關鍵字
堆是一種特殊的線性表,其特殊在哪呢?特殊在只能在線性表的一端進行插入和刪除操作,該圖是百度百科中的解釋
基於順序存儲的棧代碼實現如下
//Stack.h
#define STACK_INIT_SIZE 100
#define STACK_INCREATMENT 10
typedef enum Status
{
success,fail,overflow,underflow
};
typedef int StackEntry;
typedef struct Stack
{
int top;//top = -1表示空棧 top = stack_size-1表示棧滿
StackEntry * entry;
int stack_size;
}Stack,*StackPtr;
typedef StackPtr Ptr;
Status Stack_Init(StackPtr s);
void Stack_Destroy(StackPtr s);
int Stack_Size(StackPtr s);
bool Stack_Empty(StackPtr s);
void Stack_Clear(StackPtr s);
Status Stack_Top(StackPtr s,StackEntry * item);
Status Stack_Push(StackPtr s,StackEntry item);
Status Stack_Pop(StackPtr s,StackEntry * item);
void Stack_Print(StackPtr s);
//Stack.cpp
#include "Stack.h"
#include <stdio.h>
#include <stdlib.h>
Status Stack_Init(StackPtr s)
{
Status outcome = fail;
if(s != NULL) //不能對NULL指針進行操作
{
s->entry = (StackEntry *)malloc(STACK_INIT_SIZE*sizeof(StackEntry));
if(s->entry)
{
s->stack_size = STACK_INIT_SIZE;
s->top = -1; //表示空棧
outcome = success;
}
}
return outcome;
}
void Stack_Destroy(StackPtr s)
{
Stack_Clear(s);
if(s)
{
if(s->entry)
{
free(s->entry);
s->entry = NULL;
}
}
}
int Stack_Size(StackPtr s)
{
return (s->top+1);
}
bool Stack_Empty(StackPtr s)
{
return (s->top == -1);
}
void Stack_Clear(StackPtr s)
{
if(s)
{
s->top = -1;
}
}
Status Stack_Top(StackPtr s,StackEntry * item)
{
Status outcome = success;
if(Stack_Empty(s))
{
outcome = underflow;
}
else
{
*item = s->entry[s->top];
}
return outcome;
}
Status Stack_Push(StackPtr s,StackEntry item) //入棧
{
Status outcome = success;
if(s->top == s->stack_size-1)
outcome = overflow;
else
{
s->top++;
s->entry[s->top] = item;
}
return outcome;
}
Status Stack_Pop(StackPtr s,StackEntry * item)//出棧
{
Status outcome =success;
if(s->top == -1)
{
outcome = underflow;
}
else
{
*item = s->entry[s->top];
s->top--;
}
return outcome;
}
void Stack_Print(StackPtr s)
{
for(int i=0;i<=s->top;i++)
{
printf("%d ",s->entry[i]);
}
printf("\n");
}
//TestStack.h
#include "Stack.h"
Status Test_PushPrint(StackPtr s,StackEntry data[],int n);
Status Test_PushPop(StackPtr s,StackEntry data[],int n);
Status Test_TopSizeClearEmpty(StackPtr s,StackEntry data[],int n);
//TestStack.cpp
#include "TestStack.h"
#include <stdio.h>
#include <stdlib.h>
/*
爲方便測試結果 將下列函數中的主體移至mian.cpp中
*/
Status Test_PushPrint(StackPtr s,StackEntry data[],int n)
{
Status outcome;
outcome = Stack_Init(s);
if(outcome == success)
{
printf("順序棧建立成功\n");
for(int i=0; i<n ;i++)
{
outcome = Stack_Push(s,data[i]);
if(outcome!=success)
{
break;
}
}
}
return outcome;
}
Status Test_PushPop(StackPtr s,StackEntry data[],int n)
{
Status outcome;
StackEntry elem;
outcome = Stack_Init(s);
if(outcome == success)
{
for(int i=0 ;i<n;i++)
{
outcome = Stack_Push(s,data[i]);
if(outcome !=success)
break;
}
}
return outcome;
}
Status Test_TopSizeClearEmpty(StackPtr s,StackEntry data[],int n)
{
Status outcome;
StackEntry elem;
outcome = Stack_Init(s);
if(outcome == success)
{
for(int i=0 ;i<n ;i++)
{
outcome = Stack_Push(s,data[i]);
if(outcome !=success)
break;
}
}
return outcome;
}
//main.cpp
#include "TestStack.h"
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int size,opt =1 ,* data;
Stack stack;
Status outcome;
StackEntry elem;
while(opt!=4)
{
puts("1 測試 建立空棧 入棧 打印");
puts("2 測試 建立空棧 入棧 出棧");
puts("3 測試 建立空棧 入棧 查看棧頂元素 求棧長度 清空棧 棧是否爲空");
puts("4 退出測試");
scanf("%d",&opt);
switch(opt)
{
case 1:{
//Test_PushPrint(StackPtr s,StackEntry data[],int n)
printf("棧的長度\n");
scanf("%d",&size);
data = (StackEntry *)malloc(sizeof(StackEntry)*size);
if(data == NULL) break;
printf("輸入棧元素\n");
for(int i=0 ;i<size ;i++)
{
scanf("%d",&data[i]);
}
outcome = Test_PushPrint(&stack,data,size);
if(outcome==success)
{
Stack_Print(&stack);
}
free(data);
Stack_Destroy(&stack);
break;
}
case 2:{
//Test_PushPop(StackPtr s,StackEntry data[],int n)
printf("棧的長度\n");
scanf("%d",&size);
data = (StackEntry *)malloc(sizeof(StackEntry)*size);
if(data == NULL) break;
printf("輸入棧元素\n");
for(int i=0 ;i<size ;i++)
{
scanf("%d",&data[i]);
}
outcome = Test_PushPop(&stack,data,size);
if(outcome==success)
{
while(!Stack_Empty(&stack))
{
outcome = Stack_Pop(&stack,&elem);
printf("%d ",elem);
}
printf("\n");
}
free(data);
Stack_Destroy(&stack);
break;
}
case 3:{
//Test_TopSizeClearEmpty(StackPtr s,StackEntry data[],int n)
printf("棧的長度\n");
scanf("%d",&size);
data = (StackEntry *)malloc(sizeof(StackEntry)*size);
if(data == NULL) break;
printf("輸入棧元素\n");
for(int i=0 ;i<size ;i++)
{
scanf("%d",&data[i]);
}
outcome = Test_TopSizeClearEmpty(&stack,data,size);
if(outcome==success)
{
Stack_Top(&stack,&elem);
printf("棧頂元素爲:%d\n",elem);
}
printf("棧的長度爲:%d\n",Stack_Size(&stack));
Stack_Clear(&stack);
if(Stack_Empty(&stack) == true)
{
printf("棧已清空\n");
}
else
{
printf("清空失敗\n");
}
free(data);
Stack_Destroy(&stack);
break;
}
case 4:{
break;
}
}
}
return 0;
}
爲了做對比,我們也將基於鏈式存儲的棧代碼實現如下
Status Stack_Init(StackPtr s)
{
Status outcome = fail;
if(*s == NULL)
{
Ptr p = (Ptr)malloc(sizeof(Stack));
if(p==NULL) return outcome;
(*s) = p;
(*s)->top = NULL;
outcome = success;
}
return outcome;
}
void Stack_Clear(StackPtr s)
{
StackNodePtr p;
if(*s)
{
while ((*s)->top)
{
p = (*s)->top;
(*s)->top = (*s)->top->next;
free(p);
}
}
}
void Stack_Destroy(StackPtr s)
{
Stack_Clear(s);
if(*s)
{
free(*s);
*s = NULL;
}
}
int Stack_Size(StackPtr s)
{
int len = 0;
while((*s)->top)
{
len++;
(*s)->top = (*s)->top->next;
}
return len;
}
bool Stack_Empty(StackPtr s)
{
return ((*s)->top == NULL);
}
Status Stack_Top(StackPtr s,StackEntry * item)
{
Status outcome = success;
if(Stack_Empty(s))
{
outcome = underflow;
}
else
{
*item = (*s)->top->entry;
}
return outcome;
}
Status Stack_Push(StackPtr s,StackEntry item)
{
Status outcome = success;
StackNodePtr p = (StackNodePtr)malloc(sizeof(StackNode));
if(p == NULL)
{
outcome = overflow;
}
else
{
p->entry = item;
p->next = (*s)->top;
(*s)->top = p;
}
return outcome;
}
Status Stack_Pop(StackPtr s,StackEntry * item)
{
Status outcome = success;
if(Stack_Empty(s))
{
outcome = underflow;
}
else
{
StackNodePtr p = (*s)->top;
(*s)->top = p->next;
*item = p->entry;
free(p);
}
return outcome;
}
void Stack_Print(StackPtr s)
{
while((*s)->top)
{
printf("%d",(*s)->top->entry);
(*s)->top = (*s)->top->next;
}
printf("\n");
}