码迷,mamicode.com
首页 > 其他好文 > 详细

初识 基本数据结构和stl

时间:2021-02-19 13:18:28      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:速度   size   清空   gre   结合   数组实现   names   name   blank   

基本数据结构

双向链表

用数组模拟链表实现

双向链表初始化

l[1]=r[1]=0;r[0]=1;

结点1的左边和右边都是1,结点0的右边是1,为什么结点0会存在?因为后续元素有可能插入到结点1的前面

插入

将i插入到x的左边
  • x原本的左边为l[x]

  • 调整后的顺序为l[x],i,x

  • 想象l[x]和x有两根线牵着,现在要增加两根线,想清楚,要怎样修改,才能确保三者的练习

  • l[x]是依托x的存在而存在,不如先对与l[x]相关的数据进行修改

r[l[x]]=i;l[i]=l[x];
l[x]=i;r[i]=x;
将i插入到x的右边
  • 同理
l[r[x]]=i;r[i]=r[x];
r[x]=i;l[i]=x;

删除

删除位置位x的元素
  • x左边元素为l[x]

  • x右边元素为r[x]

  • 先解决左右两边元素的的问题

    r[l[x]]=r[x];l[r[x]]=l[x];
    

切换

从当前元素切换到下一个元素

x=r[x]

从当前元素切换到上一个元素

x=l[x]

应用——遍历

cur=0
do{
   cur=r[cur];
}while(cur!=0)

其他实现方法数组和指针

STL--变长数组vector

定义

vector<数据类型> 数组名;

添加数据

数组名.push_back(数据);

第i位数据的访问

v[i];

数组长度

  • v.size();
  • 注意变长数组的下标也是从0开始的

清空数组

v.clear()

好处

相对于二维数组不用浪费多余的内存空间

STL--栈stack

定义

stack<数据类型> 变量名

进栈

栈名.push(x)

出栈

栈名.pop()

栈长度

栈名.size()

判断栈是否为空

栈名.empty()

应用——左右括号匹配问题

  • 括号类型:()[]{}

  • 解决思路:左括号进栈,右括号判断

  • 特判:右括号进栈,栈长为0

  • 判断:退群情况:每种右括号都遇到与自己不同类型的两种相应左括号

    ? 入群情况:除退群情况外

  • 细节:

    • 数字要一次性读完(542)(在读取字符里的while语句再内嵌一个while语句)
    • 边读入边处理

STL--队列queue

定义

queue<数据类型>队列名

入队

队列名.push(数据)

离队

队列名.pop()

队头

队列名.front()

队列长度

队列名.size()

判断队列是否为空

队列名.empty()

STL--双端队列deque

定义

deque<数据类型> 队列名

头/尾部进

队列名.push_front/back(数据);

头/尾部出

队列名.pop_front/back()

头/尾部出的前提

  • 双端队列不为空
  • 不为空的情况
    1. !deque1.empty() 注:为空,返回值为0,取反为1,if才执行
    2. deque1.empty()==0 or deque1.empty()!=1
    3. deque1.empty()==false or deque1,empty()!=true

应用

单调队列的构造

  • 原理:将加入的元素与队首或队尾的元素进行比较,再根据预设的单调性决定要加入的位置

给定一个n个数的数列,从左到右输出每个区间长度为m的数列段的最大数

  • 方法一:一个一个区间段的进行查找,共需(n-m+1)*m次操作,坏处:空间复杂度高

  • 方法二:双指针法

    头指针指向头,尾指针指向尾,先根据第一个区间段确立最大值,坏处:最大值可能有多个(需要多设一个变量来统计最大值个数,比较复杂)

  • 方法三:单调队列, 先根据第一个区间创建一个单调队列,添加元素时比较头尾,长度到达m时开始去头操作

  • 方法四:单调队列,单调队列存位置

    • 加入元素为x,x所对应的值为a[x]
    • 队列长度为x-dq.front()+1大于等·x-dq.front()+1
    • 队列开始去头的条件为x-dq.front()+1>m
    • 由于去头是留到最后的,不妨把最大值的坐标留到第一位,而为了实现这样的操作,在从尾巴入的时候就要入小的,而入小的,换种想法可以把前面大的踢掉(但题目要求的是大的),所以这种想法是错的,所以队列的尾巴应该入大的,把前面小的给踢掉。
#include<iostream>
#include<deque>
using namespace std;
int main()
{
	deque<int> deque1;
	int n,m;
	cin>>n>>m;
	int a[n+1];
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
		
		while(!deque1.empty()&&a[deque1.back()]<=a[i])
		    	deque1.pop_back();
		deque1.push_back(i);
		
		while(deque1.empty()!=1&&i-deque1.front()+1>m)
		    deque1.pop_front();
	    //if(i-deque1.front()+1==m)	deque1.front()有可能被更新掉
		if(i>=m-1) 
		    cout<<a[deque1.front()]<<" ";	    
	}
	return 0;
}

1714切蛋糕

  • max(sum[i]-sum[j]) (j属于[i-(m-1),i-1])
  • 方法一是
  • sum[i]-min(sum[j])(j属于[i-(m-1),i-1])

技巧

  • 要求一个含减号的式子的最大值,若被减数是不变的,则原问题可转换为求减数的最小值
  • 若减数随区间移动而变化,可考虑使用单调队列

  • 定义:一种集合
  • 度:一个结点的子结点数
  • 叶结点:没有度的结点
  • 父结点:可以往上爬的结点
  • 子结点:可以往下跑的结点
  • 根结点:没有父节点的结点
  • 兄弟结点:与自己共用父结点的结点

二叉树

数组实现方式

  • 当前结点x
  • 左子节点l[x],建立l数组用来存放各个数的左结点
  • 右左节点r[x],建立r数组用来存放各个数的右结点
  • -1表示无该子结点
  • l[l[l[l[l[x]]]]]x的左左左左结点,寻找方法:dfs()或while()

前序遍历

void dfs(int x){
     cout<<x;
     if(l[x]!=-1)dfs(l[x]);
     if(r[x]!=-1)dfs(r[x]);
}

中序遍历

void dfs(int x){
     if(l[x]!=-1)dfs(l[x]);
     cout<<x;
     if(r[x]!=-1)dfs(r[x]);
}

应用——已知中序后序求前序

  • 思路:字符串存储,用后序最后一个元素去确认中序的的位置,然后对中序字符串分左右,并把中序的左子树的最右位置用到后序上(中序和后序的左子树部分在内容上(不包括顺序)是重合的)。

STL--优先队列

优先队列

  ``priority_queue<``int``,vector<``int``>,greater<``int``> >que3;``//注意“>>”会被认为错误, 
                           ``//这是右移运算符,所以这里用空格号隔开 

模板

priority_queue<int,vector<int>,greater/less<int> > pqx

在优先队列与结构体的结合

在优先队列中使用结构体的若干小结Goozy

模板

使用优先队列时,如果需要对Time中的start从小到大排序,有两种方法:

priority_queue<Time> pq;

一.在结构体外重载结构体小于运算符:

bool operator <(const Time& a,const Time& b){
 return a.start > b.start;
}  //这里以大于重载小于是因为默认情况下,优先队列是以大的作为队首,这样一反,就可以再默认情况下使得小的作为队首二.直接在结构体中重载小于运算符:

二.直接在结构体中重载小于运算符:

struct Time{  
 int start, end;  
 bool operator < (const Time& t)const{  
        return start > t.start;  
    }  //用大于号去重载小于号
   };  

其他

1e10和128M的关系

  • 1MB=1024KB=1024KB*1024=1048576B=1.048576e6B
  • 1int占4个字节,1e10占4e10的字节

重载

  • 重新定义

register int

register 是表示使用cpu内部寄存器(寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件)的变量,而平时的int是把变量放在内存中,存到寄存器中可以加快变量的读写速度。

断环为链

  • 二倍长度
  • a[i+n]=a[i]

初识 基本数据结构和stl

标签:速度   size   清空   gre   结合   数组实现   names   name   blank   

原文地址:https://www.cnblogs.com/BeautifulWater/p/14409737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!