数据结构随想(一)

2019-03-02  本文已影响0人  Cipolee
              #原创                

之前老是对牛顿的“站在巨人肩膀上”有点误解,咱不否认牛顿在数学,物理上的才华与对人类的贡献,因为牛顿啥人品咱也都知道,误解他在所难免。现在发现杨绛先生的“你的问题主要在于读书不多而想得太多”愈发正确,书是人们智慧的载体,天才的存在使得书更有价值。多读书,站在巨人的肩膀上是有意义的,与其活在自己的世界里踽踽独行,不如包容的心态学习前人的经验。曾一直思考,其实岁月悠悠,哦,shit,大爷直接过来把自习室灯关了,我就一人还在这黑灯瞎火的抒情,咳咳,继续,说那儿了,,,,,(此处卡顿30s)哦,你思考的问题早有人为你思考过了,多看书是快速生长的一种方法,不用摸着石头过河了嘛!

废话不多说,看题,非计算机学生慎看。

编码工作常被运用于密文或压缩传输。这里我们用一种最简单的编码方式进行编码:把一些有规律的单词编成数宇。
字母表中共有26个字母{a,b,…,z},这些特殊的单词长度不超过6且字母按升序排列。把所有这样的单词放在一起,按字典顺序排列,一个单词的编码就对应着它在字典中的位置。
例如:
a→1 b→2 z→26 ab→27 ac→28
你的任务就是对于所给的单词,求出它的编码。
输入输出格式
输入格式:
仅一行,被编码的单词。
输出格式:
仅一行,对应的编码。如果单词不在字母表中,输出0。
输入样例 :ab 输出样例:27

该题目来源于洛谷,洛谷平台未标注出题作者


OK,进入正题,首先搞清升序与非递减的区别,即按字典序升序就保证了该编码制度下没有相同的字母。

所以a->1,b->2,c->3, ,z->26,aa->27,ab->28, , ,ba->53是错误的,也就是说不能看成由a~z组成的26进制编码成10进制,对吧?

Alright,发动你聪明的小脑瓜,抽象出该题背后的数据结构,想想它长什么样子了。

那些对“数据结构”概念一脸迷茫的孩子,可以继续阅读,牛犇可以略过。

数组结构的核心技术是分解和抽象。

首先对数据进行分解和抽象,通过分解划分出数据的层次(数据-数据元素-数据项);再经过抽象,舍弃数据元素的具体内容,得到数据的逻辑结构。

其次是处理的分解和抽象,通过分解将需求划分成各个功能;再经过抽象舍弃实现细节得到算法。

好吧,我也不罗嗦了,你肯定想掌握数据结构最重要的东西吧。

逻辑结构是你学数据结构必须掌握的,否则,嘿嘿嘿,你可能要叨念"Data structure fucks me"或者"Life sucks because of data structure "了。

逻辑结构分为线性结构和非线性结构。

线性结构元素之间的关系是一对一对的,如线性表,向量,栈(重要),队列(重要),优先队列,字典等。

非线性结构可能是一对多,即树(真重要),多对多,即图(真重要)本人觉得数据结构的博大精深从这儿开始就体现出来了。

/这是我的第一篇简书:-),还可以去gitee.com/cipolee/

下面是我理解的该题背后的结构。

理科男灵魂画师一个,不会画图,呜呜呜,,

哎哎哎,对了,这才叫抽象嘛,嘿嘿嘿,逻辑结构要的就是抽象。

image

咳咳咳,前方高能。

每种逻辑结构背后都有,查找,遍历,插入,建立,删除。如果继续抽象,遍历属于查找,建立属于插入。

这个题不就是让你找到编码规律后为单词编码(第一步),存起来(第二步),然后给你个单词你往存起来的地方查找,找到你就能输出答案了,就这么easy。

第一步,编码规律你已经知道,就是上面的树,可以用DFS把树的每一条枝子(路径)即一个单词搜索一遍得到编码结果。

第二步,存起来,用什么存容易查找呢,还能代码容易实现,时间复杂度还低?

ummm,如果你够懒你会说我啥也不想用,就想给我单词我就能把编码输出。对!你这个想法很聪明,这时你会发现你需要一个由单词到数字的映射。用map存!

所有大的问题都解决,开始写代码,代码中出现的细节在代码里注释。


#include<iostream>

#include<map>

using namespace std;

map<string,int>M;//可以理解有一个M对象它从string字符串映射到一个整数及答案。

int cnt=1;

//cnt是计数器,初始a为1。

string all,one;

//all是为了给各个单词存编码而生成的所有种类的字符串(枚举的思想),而one是你要输入的字符串。

void DFS(int length,int k)//length是单词长度,k深搜的层数

{

if(k>length)//深搜边界

{

M[all]=cnt++;

return ;

}

char i,j;

if(k==1)

j='a';

else

j=all[k-2]+1;//k-2=k-1(回到上一层)-1(数组从0开始编号,找到上一个字母)+1(保证升序,大一个)

for(i=j;i<='z';i++)

{

all[k-1]=i;

DFS(len,k+1);

//为什么它就能按深搜的那个过程走一遍,你看执行到边界return,就回溯到上一层,上一层按顺序往后执行,然

//后依此类推

}

int main()

{

int n;//单词字母个数。

for(n=1;n<=6;n++)

{

all.clear();

all.resize(n);

DFS(n,1);

}

cin>>one;

cout<<M[one]<<endl;

return 0;

}

其实仔细思考DFS(depth first search深度优先搜索)和BFS(breadth first search广度优先搜索),就会发现其中的哲学思想,一个是一下子走到底,不到黄河不死心,玩深度;一个是先把最近的先走一遍,再往下走,重广度。

而栈,先进后出,队列,先进先出。这先进先出,先进后出所反映的思想在算法甚至在生活中也普遍存在。如果深度理解,你会发现DFS是栈的操作,BFS是队列的操作。

是不是发现这几行代码比一篇网络小说的信息量大多了。

新时代大学生,在每日巨大的信息冲击下,很难接受文艺的辞藻华丽的诗词,从接受信息获得快感的阈值越来越高,为此他们会浏览更多的信息,为此不浪费碎片的时间去看快手,抖音,在花花绿绿的信息流中接受须臾的感官刺激,垃圾信息害人太惨,代码中都是智慧的结晶,不仅包含的信息多,质量还高。

多读书不愿意?多读代码就好了。

image
上一篇下一篇

猜你喜欢

热点阅读