資料結構 棧(順序棧,鏈式棧,用棧實現計算器)
一、棧的概念
1. 棧是一個特殊的線性表,只能在一端操作:棧頂(top):允許操作 的一端
棧底(bottom):不允許操作的一端
2. 特點:後進先出
二、順序棧
1. 若儲存棧的長度為StackSize,則棧頂位置top必須小於StackSize
若棧存在一個元素,top = 0;空棧的條件:top = -1;
2. 結構體定義:struct sqStack
{
int top;
int
};
3. (1)棧的初始化(兩次malloc分配)
(*s) = (Stack *)malloc(sizeof(Stack) * 1); //分配一個結構體,用於儲存資訊
(*s)->top = -1; //空棧,棧頂指標為-1
(*s)->data = (ElemType *)malloc(sizeof(ElemType) * SIZE); //為棧分配空間
(2)進棧 s - > data[ s - > top + 1 ] = e; //先放入內容,再移動top指標
s - > top++;
(3)出棧 e = s - > data[ s -> top ]; //先取出內容,再移動top指標
s - > top - -;
(4)清空棧 s -> top = -1;
(5)銷燬棧 free( ( *s ) - > data );
free( *s );
*s = NULL;
三、鏈式棧
1. 棧頂放在單鏈表的頭部;
鏈棧不需要頭結點;
鏈棧不存在棧滿的情況。
2. 結構體定義:
/*結點資訊*/
struct node
{
ElemType data; //資料域
struct node *next; //指標域
};
typedef struct node Node;
/*棧的資訊*/
struct stack
{
Node *top; //頭指標
int count; //結點個數
};
3. 鏈式棧初始化時只要分配stack空間,即malloc一次,裡面節點的空間是放一個分配一個
4. 棧的鏈式儲存 原始碼
(1)LinkStack.h
#ifndef _LINKSTACK_H
#define _LINKSTACK_H
#define SUCCESS 10000
#define FAILURE 10001
#define TRUE 10002
#define FALSE 10003
typedef int ElemType;
/*結點資訊*/
struct node
{
ElemType data; //資料域
struct node *next; //指標域
};
typedef struct node Node;
/*棧的資訊*/
struct stack
{
Node *top; //頭指標
int count; //結點個數
};
typedef struct stack Stack;
int StackInit(Stack **s);
int StackEmpty(Stack *s);
int push(Stack **s, ElemType e);
int GetTop(Stack *s);
int pop(Stack **s);
int StackClear(Stack **s);
int StackDestroy(Stack **s);
#endif
(2)LinkStack.c
#include "LinkStack.h"
#include <stdlib.h>
/*初始化*/
int StackInit(Stack **s)
{
if(NULL == s)
{
return FAILURE;
}
(*s) = (Stack *)malloc(sizeof(Stack) * 1); //分配stack的空間
if(NULL == (*s))
{
return FAILURE;
}
(*s)->top = NULL;
(*s)->count = 0;
return SUCCESS;
}
/*判斷是否為空*/
int StackEmpty(Stack *s)
{
if(NULL == s)
{
return FAILURE;
}
return (s->top == NULL) ? TRUE : FALSE;
}
/*進棧*/
int push(Stack **s, ElemType e)
{
if(NULL == s || NULL == (*s))
{
return FAILURE;
}
Node *p = (Node *)malloc(sizeof(Node));
if(NULL == p)
{
return FAILURE;
}
p->data = e;
p->next = (*s)->top;
(*s)->top = p;
(*s)->count++;
return SUCCESS;
}
/*取棧頂元素*/
int GetTop(Stack *s)
{
if(NULL == s || NULL == s->top)
{
return FAILURE;
}
return s->top->data;
}
/*出棧*/
int pop(Stack **s)
{
if(NULL == s || NULL == *s)
{
return FAILURE;
}
Node *p = (*s)->top;
ElemType e = p->data;
(*s)->top = p->next;
(*s)->count--;
free(p);
return e;
}
/*清空*/
int StackClear(Stack **s)
{
if(NULL == s || NULL == *s)
{
return FAILURE;
}
Node *p = (*s)->top;
while(p)
{
(*s)->top = p->next;
free(p);
p = (*s)->top;
(*s)->count--;
}
return SUCCESS;
}
/*銷燬*/
int StackDestroy(Stack **s)
{
if(NULL == s || NULL == *s)
{
return FAILURE;
}
free(*s);
(*s) = NULL;
return SUCCESS;
}
3. TestLinkStack.c (main函式)
#include "LinkStack.h"
#include <stdio.h>
int main()
{
int ret, i;
Stack *stack = NULL;
/*初始化*/
ret = StackInit(&stack);
if(ret == SUCCESS)
{
printf("Init Link Stack Success!\n");
}
else
{
printf("Init Failure!\n");
}
/*判斷是否為空*/
ret = StackEmpty(stack);
if(ret == TRUE)
{
printf("Stack is Empty!\n");
}
else if(ret == FALSE)
{
printf("Stack is not Empty!\n");
}
else
{
printf("Stack error!\n");
}
/*進棧*/
for(i = 0; i < 10; i++)
{
ret = push(&stack, i);
if(ret = FAILURE)
{
printf("Push %d Failure!\n", i);
}
else
{
printf("Push %d Success!\n", i);
}
}
/*取棧頂元素*/
ret = GetTop(stack);
if(ret == FAILURE)
{
printf("Gettop Failure!\n");
}
else
{
printf("Top is %d\n", ret);
}
/*出棧*/
for(i = 0; i < 5; i++)
{
ret = pop(&stack);
if(ret == FAILURE)
{
printf("Pop Failure!\n");
}
else
{
printf("Pop %d is Success!\n", ret);
}
}
/*清空*/
ret = StackClear(&stack);
if(ret == FAILURE)
{
printf("Clear Failure!\n");
}
else
{
printf("Clear Success!\n");
}
/*清空後判斷是否為空*/
ret = StackEmpty(stack);
if(ret == TRUE)
{
printf("Stack is Empty!\n");
}
else if(ret == FALSE)
{
printf("Stack is not Empty!\n");
}
else
{
printf("Stack error!\n");
}
/*銷燬*/
ret = StackDestroy(&stack);
if(ret == FAILURE)
{
printf("Destroy Failure!\n");
}
else
{
printf("Destroy Success!\n");
}
/*銷燬後進棧*/
for(i = 0; i < 2; i++)
{
ret = push(&stack, i);
if(ret = FAILURE)
{
printf("Push %d Failure!\n", i);
}
else
{
printf("Push %d Success!\n", i);
}
}
return 0;
}
四、用棧的鏈式儲存結構實現計算器功能
中綴表示式轉字尾表示式情況歸納:
1. 運算元 :進棧
2. 操作符 :(1)進棧:空棧
優先順序高
棧頂是‘( ’同時表示式不是‘ )’
(2)出棧並計算:表示式符號的優先順序不高於棧頂符號
表示式為‘ )’同時棧頂不為‘( ’
表示式為‘\0’(即表示式結束)同時棧不為空
(3)出棧但不計算:表示式為‘ )’同時棧頂為‘( ’
#include "LinkStack.h"
#include <stdio.h>
int Priority(char ch)
{
switch(ch)
{
case '(':
return 3;
case '*':
case '/':
return 2;
case '+':
case '-':
return 1;
default:
return 0;
}
}
int main()
{
Stack *s_opt, *s_num;
char opt[1024] = {0}; //存放表示式
int i = 0, num1 = 0, num2 = 0, temp = 0;
if(StackInit(&s_opt) != SUCCESS || StackInit(&s_num) != SUCCESS) //棧的初始化
{
printf("Init Failure!\n");
}
printf("Please input:\n");
scanf("%s", opt);
while(opt[i] != '\0' || StackEmpty(s_opt) != TRUE) //表示式沒結束或操作符棧不為空
{
if(opt[i] >= '0' && opt[i] <= '9')
{
temp = temp * 10 + opt[i] - '0';
i++;
if(opt[i] > '9' || opt[i] < '0') //操作符
{
push(&s_num, temp);
temp = 0;
}
}
else //操作符
{
if(opt[i] == ')' && GetTop(s_opt) == '(') //出棧不計算
{
pop(&s_opt);
i++;
continue;
}
if(StackEmpty(s_opt) == TRUE ||
(Priority(opt[i]) > Priority(GetTop(s_opt)))
|| (GetTop(s_opt)) == '(' && opt[i] != ')') //出棧計算
{
push(&s_opt, opt[i]);
i++;
continue;
}
if((opt[i] == '\0' && StackEmpty(s_opt) != TRUE)
|| (opt[i] == ')' && GetTop(s_opt) != '(') ||
(Priority(opt[i]) <= Priority(GetTop(s_opt)))) //全部進棧完成開始計算
{
switch(pop(&s_opt))
{
case '+':
num1 = pop(&s_num);
num2 = pop(&s_num);
push(&s_num, (num1 + num2));
break;
case '-':
num1 = pop(&s_num);
num2 = pop(&s_num);
push(&s_num, (num2 - num1));
break;
case '*':
num1 = pop(&s_num);
num2 = pop(&s_num);
push(&s_num, (num1 * num2));
break;
case '/':
num1 = pop(&s_num);
num2 = pop(&s_num);
push(&s_num, (num2 / num1));
break;
}
}
}
}
printf("%d\n", GetTop(s_num));
return 0;
}