您的位置:首页 > 理论基础 > 数据结构算法

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

2016-11-29 16:00 501 查看
本文为《数据结构与算法分析-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++的标准库了,所以本文并没有对于表,栈以及队列的实现,只有原理以及如何应用,就酱啦~~祝学习愉快~

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息