用数组模拟链表、栈和队列

2、数据结构

2.1、单链表:主要用作邻接表(存储图、树)

使用数组模拟单链表:

const int N = 100010;
// head存储链表头,
//e[]存储节点的值,
//ne[]存储节点的next指针,
//idx表示当前节点
int head, e[N], ne[N], idx;

//初始化 
void init(){
	head = -1;
	idx = 0;
}

//将x插入到头结点 
void add_to_head(int x){
	e[idx] = x;
	ne[idx] = head;
	head = idx;
	idx ++;
}

//将x插入到下标为 k 的后面 
void add(int k, int x){
	e[idx] = x;
	ne[idx] = ne[k];
	ne[k] =idx;
	idx++;
}

//将第k个数(下标为 k-1)删除  
void remove(int k){
	ne[k] = ne[ne[k]];
} 

2.2、双链表:优化某些问题

const int N =100010;
//e[]存储节点的值,
//l[]存储节点的左指针,
//r[]存储节点的右指针,
//idx表示当前节点
int e[N], l[N], r[N], idx;

void init(){
	// 0表示左端点,1表示右端点
	r[0] = 1, l[1] = 0; 
	idx =2;
}
//在下标是K的右边插入一个 
//在下标为k的左边一个插入一个数 调用 add(l[k],x)即可
void add(int k, int x){
	e[idx] = x;
	r[idx] = r[k];
	l[idx] = k;
	l[r[k]] = idx;
	r[k] = idx;	
	idx++;
	
}

//删除下标为 k 的数 
void remove(int k){
	r[l[k]] = r[k];
	l[r[k]] = l[k];
} 

2.3、栈

用top表示栈顶所在的索引。
初始时,top = -1。表示没有元素。
pusn x :栈顶所在索引往后移动一格,然后放入x。st[++top] = x。
pop : top 往前移动一格。top–
empty :top 大于等于 0 栈非空,小于 0 栈空。top == -1 ? “YES” : “NO”
query : 返回栈顶元素。st[top]

#include <iostream>
using namespace std;

const int N = 100010;

int stack[N], top = -1;
/*
//插入
stk[++ top] = x;

//弹出
top--;

//判断栈是否为空
if(top> 0) not empty;
else empty;

//栈顶
stk[top]; 
*/
int main(){
	
	int m;
	cin>> m;
	while(m--){
		string op;
		int x;
		cin >> op;
		if(op =="push"){
			cin>>x;
			stack[++top] = x;
		
		}else if( op == "pop"){
			--top; 
		}else if( op == "empty"){
			if(top > 0)
				cout << "NO" <<endl;
			else
				cout << "YES" <<endl; 
		}else{
			cout << stack[top]<< endl;
		}
	}
	
	return 0;
} 

2.4、队列

数组模拟普通队列:

#include <iostream>
using namespace std;
const int N = 100010;
// hh 表示队头,tt表示队尾
int q[N], hh = 0, tt = -1;

int main(){
 int m;
 cin>> m;
 while(m--){
 	string op;
 	int x;
 	cin >> op;
 	if ( op == "push") {
 		cin >> x;
 		q[++tt = x;]
	 }else if ( op == "pop") {
	 	hh++;
	 }else if ( op == empty) {
		 	cout<<(hh>tt?"YES":"NO")<<endl;
	 }else {
	 	cout<<q[hh]<<endl;
	 }
 }	
	return 0;
} 

循环队列

// hh 表示队头,tt表示队尾的后一个位置
int q[N], hh = 0, tt = 0;

// 向队尾插入一个数
q[tt ++ ] = x;
if (tt == N) tt = 0;

// 从队头弹出一个数
hh ++ ;
if (hh == N) hh = 0;

// 队头的值
q[hh];

// 判断队列是否为空
if (hh != tt)
{

}

STL中的queue

#include<iostream>
#include<queue>
using namespace std;
const int N=100010;
int n;
int main(){
    queue <int> q;
    cin>>n;
    while(n--){
        string op;
        int x;
        cin>>op;
        if(op=="push"){
            cin>>x;
        	q.push(x);
        }
        else if(op=="pop")
            q.pop();
        else if(op=="empty")
            cout<<(!q.empty()?"NO":"YES")<<endl;
        else
          cout<<q.front()<<endl;
    }
    return 0;
}

单调栈:找出每个数左边离它最近的比它大/小的数
在这里插入图片描述

#include <iostream>
using namespace std;
const int N = 100010;
int n;
int stack[N], tt; //tt为零时 栈为空 
int main(){
	
	cin>> n;
	
	for(int i = 0; i < n; i++){
		
		int x;
		cin>> x;
		
		while( tt && stack[tt] >= x) tt--;
		if(tt)
			cout<< stack[tt] << " ";
		else 
			cout << -1 <<" ";
		stack[++tt] = x;
	}
	
	return 0;
} 

单调队列 :找出滑动窗口中的最大值/最小值
在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;
const int N = 100010;
int n, k;

//a作为 原数组  q作为队列 存放 下标 
int a[N], q[N];


int main(){
	
	scanf("%d%d",&n, &k);
	
	for(int i = 0; i < n; i++) scanf("%d",&a[i]);
	
	int hh = 0, tt = -1;
	
	for(int i = 0; i < n; i++){
		 //hh > tt  队列为空 ,当队列不为空,且 队头元素 在当前窗口内  
		if(hh <= tt && q[hh]<i-k+1 )
			hh++; //判断队头前元素 是否在当前窗口内 ,如果不在,也要删除 
			
		//当队列不为空 且当前a[i] 小于队列中的数,出队 
		while( hh <=tt && a[q[tt]]>= a[i]) 
			tt--; //从队尾出队 
	
		q[++tt] = i; //入队 
		
		if( i >= k - 1)
			cout<<a[q[hh]]<<" ";
	}
	puts("");	
	
	hh = 0, tt = -1;
	for(int i = 0; i < n; i ++) {
		if(hh <= tt && q[hh]<i-k+1 )
			hh++; 
		while( hh <=tt && a[q[tt]] <= a[i]) 
			tt--; //从队尾出队 
	
		q[++tt] = i; //入队 
		
		if( i >= k - 1)
			cout<<a[q[hh]]<<" ";
	}
	
	return 0;
}

kmp字符串匹配:

#include<iostream>
using namespace std;
const int N = 100010;
const int M = 1000010;
char p[N];
char s[M];

int n, m;
int ne[N];
int main(){
   
    cin>> n >> p + 1 >> m >> s + 1;
    
    //求模式串的next数组: 
    for( int i =2, j = 0; i <= n; i++ ){
    	while( j && p[i] != p[j+1]) j = ne[j];
    	if(p[i] == p[j+1]) j++;
    	ne[i]=j;
	}
    
    //匹配 
    for(int i = 1, j = 0; i <= m; i++){
    	while(j && s[i]!= p[j+1]) j = ne[j];
    	if(s[i] == p[j+1]) j++;
    	if( j == n ){
    		cout << i-n<<" ";
    		j = ne[j];
		}
	}
    
    
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值