0%

栈--顺序栈与链栈

  • 逻辑结构:线性表
  • 存储结构:顺序存储\链式存储
  • 基本运算:
    1. 初始化
    2. 判断栈空
    3. 判断栈满
    4. 入栈
    5. 出栈
    6. 取栈顶元素

注意:栈也是线性表,其特殊性在于有特殊的运算规则。即:栈结构只能在一端进行操作,该操作端称为栈顶,另一端称为栈底。按照“后进先出”(Last In First Out,LIFO)原则处理数据节点。

1. 顺序栈

  • 顺序栈的定义

1
2
3
4
5
6
typedef struct stack
{
int *base; // 基地址
int *top; // 栈顶指针
int stackSize; // 栈容量
}*Stack;
  • 顺序栈的初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Stack Init_Stack(Stack S)				// 栈的初始化
{
S=(Stack)malloc(sizeof(Stack));
if(!S)
exit(0);

S->base = (int*)malloc(STACK_INIT_SIZE*sizeof(DATATYPE));

if(!S->base)
exit(0);

S->top = S->base;
S->stackSize = STACK_INIT_SIZE;
return S;
}
  • 判断栈空

    栈底等于栈顶即为空。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int IsEmpty(Stack S)
    {
    if (S->top == S->base){
    return 1;
    }
    else{
    return 0;
    }
    }
  • 判断栈满

    栈顶减栈底等于栈容量即为栈满。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int IsFull(Stack S)
    {
    if (S->top - S->base == S->stackSize) {
    return 1;
    }
    else{
    return 0;

    }
    }
    回到目录
  • 顺序栈的入栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void Push(Stack S, DATATYPE e)				// 数据压进栈
{
assert(S);

if (IsFull(S))

{

S->base = (int*)malloc((STACK_INIT_SIZE+STACK_INCREMENT)*sizeof(DATATYPE));

if (!S->base)

exit(0); // 存储分配失败

S->top = S->base + S->stackSize;

S->stackSize += STACK_INCREMENT;

}

*S->top++ = e;

}
  • 顺序栈的出栈

1
2
3
4
5
6
7
8
9
10
DATATYPE Pop(Stack S)
{
assert(S);
if (S->top == S->base)
return 0;
else
{
return *--S->top; // *--S->top就是*(--S->top)
}
}
  • 取栈顶元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 访问栈顶 
    DATATYPE GetTop(Stack S)
    {
    assert(S);
    if (S->top == S->base)
    return 0;
    else
    {
    return *(S->top-1);
    }
    }

注意:取栈顶元素与出栈的区别:
*出栈:数据从栈中移出,
取栈顶:只是访问了一下栈顶,数据还在栈中。*

  • 顺序栈的销毁

    1
    2
    3
    4
    void DestroyStack(Stack S) {
    free(S->base);
    free(S);
    }
    回到目录
  • 总的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> // 断言函数
#define STACK_INIT_SIZE 100 // 栈容量
#define STACK_INCREMENT 10 // 栈增量

typedef int DATATYPE;

typedef struct stack
{
int *base; // 基地址
int *top; // 栈顶指针
int stackSize; // 栈容量
}*Stack;


// 栈的初始化
Stack Init_Stack(Stack S)
{
S=(Stack)malloc(sizeof(Stack));
if(!S)
exit(0);

S->base = (int*)malloc(STACK_INIT_SIZE*sizeof(DATATYPE));

if(!S->base)
exit(0);

S->top = S->base;
S->stackSize = STACK_INIT_SIZE;
return S;
}

// 判栈空
int IsEmpty(Stack S)
{
if (S->top == S->base){
return 1;
}
else{
return 0;
}
}

// 判栈满
int IsFull(Stack S)
{
if (S->top - S->base == S->stackSize) {
return 1;
}
else{
return 0;

}
}

// 操作数压栈
void Push(Stack S, DATATYPE e)
{
assert(S);

if (IsFull(S))
{

S->base = (int*)malloc((STACK_INIT_SIZE+STACK_INCREMENT)*sizeof(DATATYPE));

if (!S->base)

exit(0); // 存储分配失败

S->top = S->base + S->stackSize;

S->stackSize += STACK_INCREMENT;

}

*S->top++ = e;
}

// 操作数弹栈
DATATYPE Pop(Stack S)
{
assert(S);
if (S->top == S->base)
return 0; // 空栈弹出0保证部分负数的正确运算
else
{
return *--S->top; // *--S->top就是*(--S->top)
}
}

// 访问栈顶
DATATYPE GetTop(Stack S)
{
assert(S);
if (S->top == S->base)
return 0;
else
{
return *(S->top-1);
}
}

// 栈的销毁
void DestroyStack(Stack S) {
free(S->base);
free(S);
}

int main()
{
Stack OPND=NULL;
OPND = Init_Stack(OPND); // 创建操作数栈
int i;
for (i=0; i<5; i++)
{
Push(OPND,i);
}

for (i=0; i<5; i++)
{
printf("此时的栈顶为:%d\n",GetTop(OPND));
printf("将%d出栈\n",Pop(OPND));
}
DestroyStack(OPND);
return 0;

}

1
2
3
4
5
6
7
8
9
10
11
typedef struct node			//定义节点
{
DATATYPE data;
struct node * next;
} StackNode;

typedef struct //定义一个链栈
{
StackNode * top; //总指向栈顶
int count; //计数器 记录链栈的元素个数
}Stack,*LinkStack;
  • 链栈的初始化

1
2
3
4
5
void init(LinkStack s)
{
s->top=NULL; //该指针箭头指向为空
s->count=0; //初始化时长度为零
}
  • 判断栈空

1
2
3
4
int IsEmpty(LinkStack s)
{
return (s->top==NULL? TRUE:FALSE);
}

回到目录

  • 链栈的入栈

1
2
3
4
5
6
7
8
9
10
11
12
13
void push(LinkStack s,DATATYPE a)
{
StackNode * p=(StackNode *)malloc(sizeof(StackNode));
if(NULL==p) //申请不成功
exit(1);
else
{
p->data=a;
p->next=s->top; //将新节点的指针域指向原栈顶节点
s->top=p; //栈顶指针指向新节点
s->count++;
}
}
  • 链栈的出栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DATATYPE pop(LinkStack s)
{
DATATYPE a;
if( IsEmpty(s))
return FALSE;
else
{
a =s->top->data; //将即将弹出的数据存在a中。不存也不影响出栈操作
s->top=s->top->next;
s->count--;
free(s->top);
return a;
}
}
  • 取栈顶元素

1
2
3
4
5
6
7
8
9
DATATYPE GetTop(LinkStack S)
{
if(IsEmpty(S))
return FALSE;
else
{
return S->top->data;
}
}

回到目录

  • 总的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# include<stdio.h>
# include<stdlib.h>
# define FALSE 0
# define TRUE 1

typedef int DATATYPE;

typedef struct node //定义节点
{
DATATYPE data;
struct node * next;
} StackNode;

typedef struct //定义一个链栈
{
StackNode * top; //总指向栈顶
int count; //计数器 记录链栈的元素个数
}Stack,*LinkStack;

void init(LinkStack s); //初始化
int IsEmpty(LinkStack s); //判断是否为空(链栈一般不会为满)
void push(LinkStack s,DATATYPE a); //入栈
DATATYPE pop(LinkStack s); //出栈
DATATYPE GetTop(LinkStack S); //取栈顶元素
int length(LinkStack s); //取链栈长度

void init(LinkStack s)
{
s->top=NULL; //该指针箭头指向为空
s->count=0; //初始化时长度为零
}

int IsEmpty(LinkStack s)
{
return (s->top==NULL? TRUE:FALSE);
}

void push(LinkStack s,DATATYPE a)
{
StackNode * p=(StackNode *)malloc(sizeof(StackNode));
if(NULL==p) //申请不成功
exit(1);
else
{
p->data=a;
p->next=s->top; //将新节点的指针域指向原栈顶节点
s->top=p; //栈顶指针指向新节点
s->count++;
}
}

DATATYPE pop(LinkStack s)
{
DATATYPE a;
if( IsEmpty(s))
return FALSE;
else
{
a =s->top->data; //将即将弹出的数据存在a中。不存也不影响出栈操作
s->top=s->top->next;
s->count--;
free(s->top);
return a;
}
}

DATATYPE GetTop(LinkStack S)
{
if(IsEmpty(S))
return FALSE;
else
{
return S->top->data;
}
}

int length(LinkStack s)
{
return s->count;
}

int main(void)
{
Stack S;
init(&S); // 创建操作数栈
int i;
for (i=0; i<5; i++)
{
push(&S,i);
}

printf("链栈长度为:%d\n",length(&S));

while(!IsEmpty(&S))
{
printf("此时的栈顶为:%d\n",GetTop(&S));
printf("将%d出栈\n",pop(&S));
}
return 0;
}
  • 运行结果

    在这里插入图片描述

注意:顺序栈的栈顶指向的是即将入栈的位置,没有指着任何数据,所以栈顶减栈底可以判断是否为空或满。而链栈的指针指向的是栈顶的数据,所以s->top==NULL就可以判断是否为空。别搞混了。

回到目录

------------- Thank you for reading -------------

Title - Artist
0:00