数据结构栈与队列(待补充)
内容概要
一、栈
二、栈的应用——括号匹配问题
三、队列、双向队列
四、队列的应用——tail命令实现
1、栈
栈是种数据结构
栈的特点是后进的元素的先出
栈的构造示意图
**待补充**
栈的三个基本操作
入栈
出栈
查看栈头
查看堆是否有元素
定义一个模拟栈结构的类
class Stack: def __init__(self, max_quantity=10): self.stack = [] self.max_quantity = max_quantity def add(self, val): if len(self.stack) < self.max_quantity: self.stack.append(val) def pop(self): if self.has_element(): return self.stack.pop() def get_top(self): if self.has_element(): return self.stack[-1] def has_element(self): if len(self.stack): return True
**栈在计算机系统的应用中非常广泛和重要,有空又得了解一下**
2、栈的应用——括号匹配问题
括号匹配问题——匹配字符串中的括号,检查是否合法
比如"()[]{}"是合法的
"(]{]"是非法的
使用栈解决括号匹配问题
解决思路
遍历字符串,当遇到(,{,[(左括号,左大括号和左中括号)时,将字符(,{,[ 进栈;遇到),},] 时检查栈顶,查看是否匹配,如果匹配就出栈。
遍历完后查看栈中是否还存在元素,如果还存在元素,则匹配失败;否则匹配成功
归纳
(1)遇到 '(' , '[' , '{' 字符就进栈
(2)遇到 ')' , ']' , '}' 字符就检查栈顶是否对应,比如遇到 ')' 就检查栈顶是否为 '(' ,匹配则将栈顶出栈;如果不匹配或者栈中没有元素则匹配失败
(3)遍历完整个字符,最后查看栈中是否还存在元素,如果存在则匹配失败;如果为空就匹配成功
def check(stack): dic = {')': '(', ']': '[', '}': '{'} string = input("请输入一串字符:") for i in string: if i in ['(', '[', '{']: stack.add(i) elif i in dic: if dic[i] == stack.get_top(): stack.pop() else: print("匹配失败") break else: if stack.has_element(): print("匹配失败") else: print("匹配成功") check(stack)
使用c语言,双链表,内存池实现括号匹配功能 **有可以优化的地方**
这里发生了一个错误,在使用链表时,要特别注意,就是指针指向NULL时,访问指针的成员是会报错的
#include <stdio.h> #include <stdlib.h> #define MAX_POOL_NUM 5 int pool_num = 0; struct Char{ char ch; struct Char *next; struct Char *previou; }; struct Char *top = NULL; struct Char *pool = NULL; void add(char); int add_pool(struct Char *); void pop(); struct Char *pop_pool(); char get_top(); void add(char ch){ struct Char *pch; pch = pop_pool(); if (pch == NULL){ if((pch = (struct Char *)malloc(sizeof(struct Char))) == NULL){ printf("open mem error!\n"); exit(EXIT_FAILURE); } } pch->next = NULL; pch->previou = NULL; // important pch->ch = ch; if (top == NULL){ top = pch; } else{ top->next = pch; pch->previou = top; top = pch; } } struct Char *pop_pool(){ struct Char *pch = NULL; if (pool != NULL){ pch = pool; pool = pool->next; pch->next = NULL; pool_num--; } return pch; } void pop(){ int result; struct Char *pch; struct Char *tmp; tmp = top; top = top->previou; if (top != NULL){ top->next = NULL; tmp->previou = NULL; } result = add_pool(tmp); if (result == 0){ free(tmp); } } int add_pool(struct Char * tmp){ if (pool_num < MAX_POOL_NUM){ tmp->next = pool; pool = tmp; pool_num++; return 1; } return 0; } char get_top(){ if (top != NULL){ return top->ch; } else{ exit(EXIT_FAILURE); } } int main(void){ char strings[64]; char *pstr; int sign = 0; scanf("%s", strings); for (pstr=strings; *pstr; pstr++){ switch (*pstr){ case '(': case '[': case '{': add(*pstr);break; case ')': if (top == NULL){ sign = 1; break; } if (get_top() == '('){ pop(); } else{ sign = 1; } break; case ']': if (top == NULL){ sign = 1; break; } if (get_top() == '['){ pop(); } else{ sign = 1; } break; case '}': if (top == NULL){ sign = 1; break; } if (get_top() == '{'){ pop(); } else{ sign = 1; } break; } if (sign){ printf("error!!!\n"); break; } } if (!sign){ printf("successful!!!\n"); } }
3、队列
队列也是种数据结构
队列的特点是先进的数据先出
队列结构的示意图
**待补充**
队列的基本操作
出队——出队的地方叫做队头
入队——入队的地方叫做队尾
队列的实现方式之一——环形结构
环形结构原理
**待补充**
环形结构示意图
**待补充**
使用列表实现队列的环形结构
class Queue: def __init__(self, quantity=10): self.queue = [0 for _ in range(quantity)] self.quantity = quantity self.head = 0 self.end = 0 def is_fill(self): if (self.head + 1) % self.quantity == self.end: # 这个列表实现的队列的长度为quantity-1,而不是quantity return True def has_element(self): if self.head != self.end: return True def add(self, val): if not self.is_fill(): self.queue[self.head % self.quantity] = val self.head += 1 def pop(self): if self.has_element(): self.end += 1 queue = Queue() for i in range(10): queue.add(i) for i in queue.queue: print(i)
双向队列
双向队列是既可以在队尾插入,也可以在队头插入
同时可以在队尾删除,也可以在队头删除的一种队列
4、队列的应用——tail命令的实现
linux中的tail命令,就是读取文件的最后几行;行数由参数决定
python有队列的内置模块,使用这个模块可以简单的实现tail命令
python的内置模块是双向队列
from collections import deque dq = deque([1, 2, 3], 5) # 第一个参数初始化队列,第二个参数规定队列最大元素数量 dq.append(4) # 在队头插入 print(dq) dq.popleft() # 在队尾删除 print(dq) dq.appendleft(5) # 在队尾插入 print(dq) dq.pop() # 在队头删除 print(dq) dq.extend([4, 5]) # 在队头插入多个元素 print(dq) dq.append(6) # 当队列已满时,再插入数据,会将另一端的元素删除再插入 print(dq)
使用队列实现tail命令
def tail(file, lines_count=1): with open(file, mode='r', encoding='utf-8') as fp: dq = deque(fp, lines_count) for i in dq: print(i, end='') tail('a.txt', 3)
使用自定义的队列类实现tail命令 **使用环形队列还是有问题的,问题是内置模块会将多余的删除;而环形队列删除时是通过移动剪头实现的,而非真正的删除,这导致了遍历时出现问题**
使用__call__方法出现了问题(果然得多实践,好记性不如烂笔头啊)

class Queue: def __init__(self, quantity=10): self.queue = [0 for _ in range(quantity)] self.quantity = quantity self.head = 0 self.end = 0 def is_fill(self): if (self.head + 1) % self.quantity == self.end: return True def has_element(self): if self.head != self.end: return True def add(self, val): if not self.is_fill(): self.queue[self.head % self.quantity] = val self.head += 1 else: self.pop() self.add(val) def pop(self): if self.has_element(): self.end += 1 def __call__(self): if self.head % self.quantity > self.end % self.quantity: for i in range(self.end, self.head): print(self.queue[i], end='') elif self.head % self.quantity < self.end % self.quantity: for i in range(0, self.head): print(self.queue[i], end='') for i in range(self.end, self.quantity): print(self.queue[i], end='') def tail(file, lines_count=1): with open(file, mode='r', encoding='utf-8') as fp: queue = Queue(lines_count+1) for i in fp: queue.add(i) print(queue)
**有时间优化一下好了**
class Queue: def __init__(self, quantity=10): self.queue = [0 for _ in range(quantity)] self.quantity = quantity self.head = 0 self.end = 0 def is_fill(self): if (self.head + 1) % self.quantity == self.end: return True def has_element(self): if self.head != self.end: return True def add(self, val): if not self.is_fill(): self.queue[self.head % self.quantity] = val self.head += 1 else: self.pop() self.add(val) def pop(self): if self.has_element(): self.end += 1 def tail(file, lines_count=1): with open(file, mode='r', encoding='utf-8') as fp: queue = Queue(lines_count+1) for i in fp: queue.add(i) if queue.head % queue.quantity > queue.end % queue.quantity: for i in range(queue.end % queue.quantity, queue.head % queue.quantity): print(queue.queue[i], end='') elif queue.head % queue.quantity < queue.end % queue.quantity: for i in range(0, queue.head % queue.quantity): print(queue.queue[i], end='') for i in range(queue.end % queue.quantity, queue.quantity): print(queue.queue[i], end='') tail('a.txt', 4)
**待补充**
本文来自博客园,作者:口乞厂几,转载请注明原文链接:https://www.cnblogs.com/laijianwei/p/14642071.html