0x01 栈
栈是允许在同一端进行插入和删除操作的特殊的数据结构。被允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom)。栈底固定,而栈顶浮动。栈中元素个数为零时称为空栈,插入称为进栈(Push),删除则称为退栈(Pop)。
栈的一个典型特征就是先进后出。
1 |
|
我们通过一个栈的实际应用继续加深理解,现在我们需要实现编译器中的符号成对检测。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
122bool isLeft(char c)
{
bool ret = false;
switch(c) {
case '<':
case '(':
case '[':
case '{':
case '\'':
case '\"':
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
bool isRight(char c)
{
bool ret = false;
switch(c) {
case '>':
case ')':
case ']':
case '}':
case '\'':
case '\"':
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
bool match(char left, char right) {
bool ret = false;
switch (left) {
case '<':
ret = (right == '>');
break;
case '(':
ret = (right == ')');
break;
case '[':
ret = (right == ']');
break;
case '{':
ret = (right == '}');
break;
case '\'':
ret = (right == '\'');
break;
case '\"':
ret = (right == '\"');
break;
default:
break;
}
return ret;
}
bool scanner(const char *code) {
bool ret = false;
int i = 0;
StackList *list = Stack_Create();
while (code[i] != '\0') {
if (isLeft(code[i])) {
Node *n = (Node *)malloc(sizeof(Node));
n->val = code[i];
Stack_Push(list, n);
}
if (isRight(code[i])) {
Node *n = Stack_Pop(list);
char c = n->val;
if(n == NULL || !match(c, code[i])) {
NSLog(@"%c没有匹配的符号", c);
}
free(n);
}
i++;
}
if (Stack_Empty(list) && code[i] == '\0') {
NSLog(@"匹配完成");
}else{
NSLog(@"代码不合法");
}
Stack_Destroy(list);
return ret;
}
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
const char* code1 = "#import<ViewController.h> ";
const char* code2 = "#import<ViewController.h"; // 把>去掉
scanner(code1); // 代码运行: 匹配完成
scanner(code2); // 代码运行: 代码不合法
}
@end
0x01 队列
队列是一种只允许前端(front)进行删除操作,而在后端(rear)进行插入操作的数据结构。最先插入的元素将是最先被删除的元素,反之最后插入的元素将是最后被删除的元素。因此队列的特性是先进先出。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
// 节点结构
typedef struct _node {
void *val;
struct _node *next;
}Node;
typedef struct _queue {
int length;
struct _node *front;
struct _node *rear;
}QueueList;
QueueList* Queue_Create() {
QueueList *list = (QueueList *)malloc(sizeof(QueueList));
if(list != NULL) {
list->length = 0;
list->front = NULL;
list->rear = NULL;
}
return list;
}
STATUS Queue_Append(QueueList *list, void *val) {
bool ret = list != NULL && val != NULL;
if(!ret) return ERROR;
Node *node = (Node *)malloc(sizeof(Node));
if(!node) return ERROR;
node->val = val;
if(list->length == 0) {
list->front = node;
list->rear = node;
}else{
list->rear->next = node;
list->rear = node;
}
list->length++;
return SUCCESS;
}
void* Queue_Retrieve(QueueList *list) {
if(list == NULL || list->length == 0) return NULL;
void *ret = NULL;
Node *node = list->front;
ret = node->val;
list->front = node->next;
list->length--;
if(list->length == 0) {
list->front = NULL;
list->rear = NULL;
}
return ret;
}
bool Queue_Empty(QueueList *list) {
return list->length == 0;
}
void Queue_Clear(QueueList *list) {
while(!Queue_Empty(list)) {
Queue_Retrieve(list);
}
}
void Queue_Destroy(QueueList *list) {
Queue_Clear(list);
free(list);
}
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
QueueList *list = Queue_Create();
Queue_Append(list, (void *)12);
Queue_Append(list, (void *)29);
Queue_Append(list, (void *)82);
Queue_Append(list, (void *)35);
Queue_Append(list, (void *)73);
int total = list->length;
for (int i = 0; i < total; i++) {
int n = (int)Queue_Retrieve(list);
NSLog(@"出队列:%d", n);
}
Queue_Destroy(list);
}
@end