周总结:总体上来,这周的学习内容相对来说很杂乱,也有点难,尤其是链表,模拟链表,因为是刚刚接触,所以在遇到题目的时候,首先是不会用,而且模拟链表中也还尚存着部分知识没有理解。然后牵扯到的dfs还有bfs还是没有办法灵活的运用。最近一周都没有怎么写题,感觉收获比较少,下周我希望自己能够多做一些题目,而不是单纯的学语法,因为仅仅是学习语法,我还是不能做题,而且我也发现,还是要先把基础知识要打牢。
一:链表
二:栈和队列
三:bfs和dfs
一:链表
首先在链表里面如果是使用指针,一是时间会很长,二是写起来会很麻烦。所以在写链表的时候,经常会模拟链表。
在模拟链表的时候其实还是指针的思想,但是这个指针我们通常用数组表示
规定:数组e[n]用来存放元素 ne[n]用来代指指针,用于指向下一个数据的位置。一般h[a]是指头指针,在链接表中会经常用到,我们也可以用head。如地址为空我们指定他为-1.这个知识点我们后面在遍历数组的时候会经常用到。
链表模拟时,可以分为头插法,或者是指定位置插入
//头插入法
void add_head(int a)
{
e[idx]=a;
ne[idx]=head;
head=idx++;//这里的话刚开始可能就不是特别的好理解,首先存放数据懂了,ne[idx]=head就是说让头指针指向你这个地址,因为本来说,头地址应该是指向下一个地址的但是你插入新的数字,那就更改一下,然后再让更新一下头地址
}
//刚开始我们规定head=-1; idx=0;
//指定位置插入
void add(int k,int a)
{
e[idx]=a;
ne[idx]=ne[k];
ne[k]=idx++;
}
//删除操作的话
void remove(int k)
{
ne[k]=ne[ne[k]];
}//这个就很好理解,只要是断开你想删除的数两边的链接就可以了。
二:栈和队列
栈<stack>是先进后出;
限定只能在栈顶进行插入和删除操作
3、栈的常用操作为:
(1)弹栈,通常命名为pop
(2)压栈,通常命名为push
(3)求栈的大小size
(4)判断栈是否为空empty
(5)获取栈顶元素的值top
队列<queue>是先进先出;
添加元素时,元素只能从队尾一端进入队列
元素只能从队首出队列
q.empty(); //判断队列是否为空
q.size(); //返回队列长度
q.push(item); //对于queue,在队尾压入一个新元素
q.front(); //返回队首元素的值,但不删除该元素
q.back(); //返回队尾元素的值,但不删除该元素
q.top(); //返回具有最高优先级的元素值,但不删除该元素
三:bfs和dfs
1.bfs
通常和队列放在一起使用,在遍历一个有向图还有无向图的时候经常也会使用vector去构建邻接表
而构建邻接表的方式如下:
vector<int>g[100]; for(int i=1;i<=n;i++) { int a,b; cin>>a>>b; g[a].push_back(b); g[b].push_back(a);//无向图才加上这条语句 }//这就是邻接表的构建方式,比数组简单太多了
然后我们如何写bfs语句呢
要根据题目让求什么;
大致框架:
void bfs(int u) { queue<int>q; q.push(u); st[u]=true;//标记已经遍历 while(!q.empty()) { int t=q.front(); 想要的语句 q.pop(); for(int i=0;i<g[t].size;i++) { if() 语句 q.push(g[t][i]); } } }
2.dfs
邻接表的遍历就和上面是一样的
主要是函数
大致模板
vector<int> g[100]; void dfs(int u) { if(!st[u]) cout<<u<<" "; st[u]=true; int i; for(int i=0;i<g[u].size();i++) { if(!st[g[u][i]) dfs(g[u][i]); } }
当然还有数组的方式,但是没有那么简单。
我在note上面总结的有
除此之外,迷宫问题是dfs 和bfs的经典问题,我在note上面也写得有:BFS和DFS
完结!!!!