基础算法——数据结构

以下算法均为用数组替代迭代器来进行(除了最后的stl),是针对算法竞赛而使用的,使用数组进行代码实现时间复杂度比用stl少,但会浪费部分空间,因此不考虑实际项目.

单链表

一.主体思想

使用value[N]数组储存当前位置的值,用nex[N]数组存储当前位置的下一个指向下一个位置,head存储头节点的指向,flag为当前位置.

二.重要代码

(1).链表初始化

当前位置为0,头结点指向空

代码:

void init()
{
	head = -1;
	flag = 0;
}

(2).表头插入

插入的数字指向表头的指向,表头指向插入的数字

代码:

void remove(int x)
{
	ne[x] = ne[ne[x]];
}

(3).删除

让指向删除的数的数指向删除的数指向的数(多读几遍qwq)

代码:

void insert(int k, int x)
{
	val[flag] = x;
	ne[flag] = ne[k];
	ne[k] = flag;
	flag++;
}

(4).任意位置后插入一个数

让插入的数字指向被插入的数的指向,被插入的数指向插入的数字

代码:

void insert(int k, int x)
{
	val[flag] = x;
	ne[flag] = ne[k];
	ne[k] = flag;
	flag++;
}

三.整体代码

#include<iostream>

using namespace std;

const int N = 10010;

int val[N], ne[N];
int head, flag;

void init()
{
	head = -1;
	flag = 0;
}

void add_head(int x)
{
	val[flag] = x;
	ne[flag] = head;
	head = flag;
	flag++;
}

void insert(int k, int x)
{
	val[flag] = x;
	ne[flag] = ne[k];
	ne[k] = flag;
	flag++;
}

void remove(int x)
{
	ne[x] = ne[ne[x]];
}

int main()
{
	int round;
	cin >> round;
	init();
	while (round--)
	{
		char order;
		int k, x;
		cin >> order;
		if (order == 'H')
		{
			cin >> x;
			add_head(x);
		}
		else if (order == 'D')
		{
			cin >> k;
			if (!k)	head = ne[head];
			remove(k - 1);
		}
		else
		{
			cin >> k >> x;
			insert(k-1, x);
		}
		for (int i = head; i != -1; i = ne[i])
		{
			cout << i << " " << val[i] << " "<<endl;
		}
		cout << endl;
	}
	return 0;
}

四.例题
AcWing——826单链表

双链表

一.主体思想

val[N]数组存储当前位置的值,用l[N]存储当前位置左边的指向,用r[N]存储当前位置右边的指向,flag为当前位置.

二.重要函数

(1)重置链表

用0代替头结点,用1代替尾节点,则最开始l[0]指向最右边1,r[1]指向最左边0,则flag从2开始

代码:

void init()
{
	r[0] = 1;
	l[1] = 0;
	flag = 2;
}

(2)头插入数据

当前位置右边指向表头的右指向向,左边指向表头,表头的右指向的位置左边指向当前位置,表头右指向表头

代码:

void add_head(int x)
{
	val[flag] = x;
	l[flag] = 0;
	r[flag] = r[0];
	l[r[flag]] = flag;
	r[0] = flag;
	flag++;
}

(3)尾插入数据

当前位置左边指向表尾的左指向,右边指向标为,表尾的左指向的位置向右指向当前位置,表尾向左指向当前位置

代码:

void add_end(int x)
{
	val[flag] = x;
	l[flag] = l[1];
	r[flag] = 1;
	r[l[flag]] = flag;
	l[1] = flag;
	flag++;
}

(4)任意位置后方或前方插入一个数字

*1.后方插入:

当前位置向右指向被插入位置的右指向,向左指向被插入的位置,被插入位置的右指向向左指向当前位置,被插入的位置向右指向当前位置.

代码:

void insert(int k,int x)
{
	val[flag] = x;
	r[flag] = r[k];
	l[flag] = k;
	r[k] = flag;
	l[r[flag]] = flag;
	flag++;
}

*2.前方插入:

同理与向右插入,相当于插入位置的左指向位置的右边插入一个位置.

重要代码:

之前的k替换成r[l[k]].

(5)删除某一位置

需要删除的位置左指向向右指向删除位置的右指向,需要删除的位置的右指向向左指向删除位置的左指向.

代码:

void remove(int k)
{
	l[r[k]] = l[k];
	r[l[k]] = r[k];
}

三.整体代码:

#include<iostream>

using namespace std;

const int N = 100010;
int l[N], r[N],val[N];
int flag;

void init()
{
	l[1] = 0;
	r[0] = 1;
	flag = 2;
}

void insert(int k,int x)
{
	val[flag] = x;
	r[flag] = r[k];
	l[flag] = k;
	r[k] = flag;
	l[r[flag]] = flag;
	flag++;
}

void add_head(int x)
{
	val[flag] = x;
	l[flag] = 0;
	r[flag] = r[0];
	l[r[flag]] = flag;
	r[0] = flag;
	flag++;
}

void add_end(int x)
{
	val[flag] = x;
	l[flag] = l[1];
	r[flag] = 1;
	r[l[flag]] = flag;
	l[1] = flag;
	flag++;
}

void remove(int k)
{
	l[r[k]] = l[k];
	r[l[k]] = r[k];
}

int main()
{
	int round;
	cin >> round;
	init();
	while (round--)
	{
		int k, x;
		string order;
		cin >> order;
		if (order == "L")
		{
			cin >> x;
			insert(0, x);
		}
		else if(order=="R")
		{
			cin >> x;
			insert(l[1],x);
		}
		else if(order=="D")
		{
			cin >> k;
			remove(k+1);
		}
		else if (order == "IL")
		{
			cin >> k >> x;
			insert(l[k+1], x);
		}
		else if (order == "IR")
		{
			cin >> k >> x;
			insert(k+1, x);
		}
	}
	for (int i = r[0]; i != 1; i = r[i])
	{
		cout << val[i] << " ";
	}
	return 0;
}

一.主要思想

用stk[N]数组存储栈的值,用tt表示栈顶的位置,通过tt的改变来进行栈的变化

二.主要代码:
1.插入

每存一个数让tt加一,从而做到先入后出

void insert(int x)
{
	stk[++tt] = x;
}

2.删除

直接让tt加一,栈顶位置往前缩一位,此位置有新的数据输入时被更新.

void remove()
{
	tt--;
}

3.判断栈是否为空

对栈顶的位置进行判断,如果栈顶位置为0则为空

bool judge()
{
	if (tt > 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}

单调栈

例题:
牛客竞赛 Early Orders
AcWing 单调栈
题解:
牛客竞赛 Early Orders

队列

一.主要思想

用q[N]数组代替队列,用hh指向队首,用tt指向队尾,通过队首hh的变化从而达到队列的效应

二.关键代码
(1)插入数据

每存一个数让tt(队尾)加一,每次取数从hh(队首)取,从而达到先入先出.

代码:

void insert(int x)
{
	q[++tt] = x;
}

(2)删除数据

直接让hh(队首)加一,此位置抛弃.

代码:

void remove()
{
	hh++;
}

(3)判断队列是否为空

如果hh(队首)大于tt(队尾)即为空

代码:

bool judge()
{
	if (hh <= tt)
	{
		return false;//非空	
	}
	else
	{
		return true;
	}
}

(4)输出队首元素

直接输出hh(队首)的数据

代码:

int check_head()
{
	return q[hh];
}

单调队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值