算法与数据结构基础----表,栈和队列(外加map用法)

本文为《数据结构与算法分析-C语言分析》Mark Allen Weiss 的读书笔记 Chapter3

Chapter 3 表,栈和队列
这部分主要介绍:
○抽象数据类型(ADT)的概念
○阐述如何对表进行有效操作
○介绍栈ADT以及在递归里的应用
○介绍队列ADT在操作系统和算法设计中的应用

抽象数据类型(abstract data type, ADP)是一些操作的集合。抽象数据类型是数学的抽象;在ADT的定义中根本没有涉及如何实现操作的集合。这可以看作是模块化设计的扩充。
//上面这段话看着有些蛋疼,接着往下看好了。

1.表ADT

①定义:我们将处理一般的形如 A1,A2,A3,...,AN 的表。我们说这个表的大小是N。大小为0的表格称为空表(empty list)
②简单数组实现的方式:直接用数组来储存一个表,直观上来看就非常简单(形式好像就一样),但在进行一些诸如插入几个数值的时候就有些捉襟见肘了。例如想在0位置插入一个数值就相当于要把所有数据往后挪一位,占用了大量的资源;类似的删除的最坏情况也是O(N)。
链表:作用就是避免简单数组在插入和删除中的线性开销。
如下图所示,很好展示了链表的工作方式,如果想删除某个特定的数值,直接让上一块的指针指向后一块即可;相似的,如果要插入,直接改变下指针的指向即可,这种方式很有效地节约了这几种操作的占用资源情况。
这里写图片描述
C++调用标准库list
//偷个懒
只有++或者- -操作,直观上用起来非常不顺手,想访问链表里第i个数据只能从头开始不断地++(i-1)次才能定位到数据然后访问。
//当然定位到末尾不断地–也是可以的,毕竟这是一个双向链表……

#include<list>
#include<iostream>
using namespace std;
//list的使用方法
//@zmdsjtu@163.com 2016//11/29 
int main() {    
    list<int> 一个链表{0,1,2,3,4,50,6};
    auto a=一个链表.begin();    
    for (int i = 0; i < 7; i++) {       
        cout << *(a) << endl;
        ++a;
    }
    一个链表.insert(a, 100);
    cout << *(--a) << endl;
    system("pause");
}

2.栈ADT

(stack)是限制插入和删除只能在一个位置上进行的表,这个位置是表的末端,叫做栈的顶(top)。
基本操作有Push(进栈)和Pop(出栈)两种
这里写图片描述
栈的模型是存在某个元素位于栈顶,这个元素也是唯一可见的。
//换句话说,相当于叠罗汉,只能看到最上面的,也只能网上堆,卸下来也只能先卸上面的……
这里写图片描述
C++调用标准库stack

#include<stack>
#include<iostream>
#include<string>
using namespace std;
//stack的使用方法
//@zmdsjtu@163.com 2016//11/29 
int main() {
    stack<string> 一个栈;//这里用string,其他各种数据类型都是一样的
    for (int i=0;i<141;i++){
        string 一个string="女票期望的我的体重是:";
        一个string += to_string(i);
        一个string += "斤";
        一个栈.push(一个string);//给栈依次push进去0到140
    }
    cout << "栈最顶端的是——"<<一个栈.top()<<endl;//访问最顶端
    for (int i = 0; i < 10; i++)
        一个栈.pop();//最顶端丢掉10次
    cout << "pop10次后顶端的是——" << 一个栈.top() << endl;//访问最顶端
    system("pause");
}

运行结果为:
这里写图片描述

3.队列ADT

队列(queue)同样也是表,但使用队列时插入在一端进行而删除在另一端进行。
大概像一个火车隧道,只能一端进一端出。
这个队列模型图也很直观,Enqueue进,Dequeue出。
这里写图片描述
C++调用双端队列deque使用代码如下:

#include<deque>//双端队列
#include<iostream>
#include<string>
using namespace std;
int main() {
    deque<string> 一个队{"今天看完第三章","或许还能看点儿第四章"};
    cout << 一个队[0]<<endl;//deque支持直接访问下标
    一个队.push_back("233,仿佛在开玩笑");//在队列后面加一项
    cout << 一个队.back() << endl;//显示最后一项
    一个队.pop_back();//逆向的出队
    cout << 一个队.back() << endl;
    system("pause");
}

运行结果如图:
这里写图片描述

4.ADT小结

以上的表,栈和队列主要用以阐述抽象数据类型的具体实现和功能是分开的。
另一种定义方式://摘自百度百科,或许看起来更直观

一个数学模型以及定义在该模型上的一组操作。抽象数据类型需要通过固有数据类型(高级编程语言中已实现的数据类型)来实现。抽象数据类型是与表示无关的数据类型,是一个数据模型及定义在该模型上的一组运算。对一个抽象数据类型进行定义时,必须给出它的名字及各运算的运算符名,即函数名,并且规定这些函数的参数性质。一旦定义了一个抽象数据类型及具体实现,程序设计中就可以像使用基本数据类型那样,十分方便地使用抽象数据类型。

关键:使用它的人可以只关心它的逻辑特征,不需要了解它的存储方式。定义它的人同样不必要关心它如何存储。


最后给一个写程序中机油安利的一个或许挺实用的map功能,可以很方便地映射,代码很直观也很简单。

#include<map>
#include<iostream>
#include<string>
using namespace std;
int main() {
    map<string, int> 一个map = { {"十一",11 },{"十二",12} };
    cout << 一个map["十一"];
    system("pause");
}

直接调用C++的标准库了,所以本文并没有对于表,栈以及队列的实现,只有原理以及如何应用,就酱啦~~祝学习愉快~

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱铭德

五毛也是爱٩(●´৺`●)૭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值