数据结构栈与队列(待补充)

内容概要

  一、栈

  二、栈的应用——括号匹配问题

  三、队列、双向队列

  四、队列的应用——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)
View Code

 

  **有时间优化一下好了**

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)

  **待补充**

posted @ 2021-04-10 20:52  口乞厂几  阅读(75)  评论(0)    收藏  举报