蒟蒻的数据结构与算法通关

前言:

创作日期:2024/4/10,预计结束时间:20天,目的:巩固所学。

数据结构:

第一章:链表

概要:1、单链表。2、循环链表。3、双链表。

#include <bits/stdc++.h>
#define MAXSIZE 100
using namespace std;

typedef struct ListNode {
	int data;
	ListNode* nextNode;
} Node;

void init(Node* head) {
	head->nextNode = nullptr;
}

void delete_(Node* head, int position) {
	Node* curr = head;
	int cnt = 0;
	while (curr->nextNode != nullptr) {
		cnt++;
		if (cnt == position) {
			Node* temp = curr->nextNode;
			curr->nextNode = temp->nextNode;
			delete (temp);
			return ;
		}
		curr = curr->nextNode;
	}
}

void print(Node* head) {
	Node* curr = head->nextNode;
	while (curr != nullptr) {
		cout << curr->data << " ";
		curr = curr->nextNode;
	}
	cout << endl;
}

void modify(Node* head, int position, int val) {
	Node* curr=head;
	int cnt=0;
	while(curr->nextNode!=nullptr) {
		cnt++;
		if(cnt==position) {
			curr->nextNode->data=val;
			return ;
		}
		curr=curr->nextNode;
	}
}

void headInsert(Node* head, int val) {
	Node* curr = head;
	Node* newNode = new (Node);
	newNode->data = val;
	newNode->nextNode = curr->nextNode;
	curr->nextNode = newNode;
}

void tailInstert(Node* head, int val) {
	Node* curr=head;
	while(curr->nextNode!=nullptr) {
		curr=curr->nextNode;
	}
	Node* newNode=new(Node);
	newNode->data=val;
	newNode->nextNode=nullptr;
	curr->nextNode=newNode;
}

void destroy(Node* head) {
	Node* curr=head->nextNode;
	while(curr!=nullptr) {
		Node* temp=curr;
		curr=curr->nextNode;
		delete(temp);
	}
	head->nextNode=nullptr;
}

void isEmpty(Node* head) {
	if (head->nextNode == nullptr)
		cout << "EMPTY LIST!" << endl;
}

int listSize(Node* head) {
	Node* curr=head;
	int cnt=0;
	while(curr->nextNode!=nullptr) {
		curr=curr->nextNode;
		cnt++;
	}
	return cnt;
}

int main() {
	Node* head = new (Node);
	init(head);
	isEmpty(head);
	headInsert(head, 1);
	headInsert(head, 2);
	headInsert(head, 3);
	print(head);
	delete_(head, 2);
	print(head);
	tailInstert(head, 4);
	tailInstert(head, 5);
	print(head);
	modify(head, 3, 6);
	print(head);
	cout<<listSize(head)<<endl;
	destroy(head);
	isEmpty(head);
	return 0;
}
单链表:
#include <bits/stdc++.h>
#define elemtype int
#define N 10

using namespace std;

typedef struct LinkList{
    elemtype data;
    LinkList* next;
} L;

elemtype tail_insert(L* head, int val) {
	L* curr=head;
	L* newNode=new(L);
	if(!curr->next) {
		curr->next=newNode;
	} else {
		while(curr->next!=nullptr) {
			curr=curr->next;
		}
		curr->next=newNode;
	}
	newNode->data=val;
	return 1;
}

elemtype head_insert(L* head, int val) {
	L* curr=head;
	L* newNode=new(L);
	if(!curr->next) {
		curr->next=newNode;
	} else {
		L* temp=curr->next;
		curr->next=newNode;
		newNode->next=temp;
	}
	newNode->data=val;
	return 1;
}

bool list_empty(L* head) {
	return head->next==nullptr;
}

void list_print(L* head) {
	if(list_empty(head))
		return ;
	L* curr=head;
	while(curr!=nullptr) {
		cout<<curr->data<<"->";
		curr=curr->next;
	}
	cout<<"nullptr";
}

elemtype list_length(L* head) {
	L* curr=head;
	int cnt=0;
	while(curr->next!=nullptr) {
		cnt++;
	}
	return cnt;
}
elemtype find(L* head, int key) {
	if(key<0 || key>=list_length(head)) {
		throw out_of_range("索引越界。");
	}
	L* curr=head;
	int i=0;
	while(i!=key) {
		i++;
		curr=curr->next;
	}
	return curr->data;
}
int main() {
    L* head=new(L);
    int value=6;
    tail_insert(head, value);
    
    return 0;
}

第二章:栈

顺序栈:
#include <bits/stdc++.h>
#define elemtype int
#define size 10

using namespace std;

typedef struct Stack {
	elemtype data[size];
	elemtype top;
} S;

void initStack(S* s) {
	s->top=-1;
}

bool isEmpty(S* s) {
	return s->top==-1;
}

bool isFull(S* s) {
	return s->top==size-1;
}

int push(S* s, elemtype val) {
	if(isFull(s)) {
		throw out_of_range("栈满。");
	}
	s->data[s->top++]=val;
	return 1;
}

int pop(S* s) {
	if(isEmpty(s)) {
		throw out_of_range("栈空");
	}
	return s->data[s->top--];
}

int main() {
	S* s=new(S);
	initStack(s);
	return 0;
}
链栈:

第三章:队列

顺序队列:
#include <bits/stdc++.h>
#define size 10
using namespace std;

typedef struct Queue {
	int data[size];
	int front, rear;
} Q;

void init(Q* q) {
	q->front=0, q->rear=0;
}

bool isEmpty(Q* q) {
	return q->front==q->rear;
}

bool isFull(Q* q) {
	return q->rear==size-1;
}

void enQueue(Q* q, int val) {
	if(isFull(q)) {
		return ;
	}
	q->data[q->rear++]=val;
}

int deQueue(Q* q) {
	if(isEmpty(q)) {
		cout<<"empty queue!"<<endl;
		return -1;
	}
	return q->data[q->front++];
}

int getFront(Q* q) {
	return q->data[q->front];
}
int main() {
	Q* q=new(Q);
	init(q);
	enQueue(q, 2);
	enQueue(q, 1);
	cout<<getFront(q)<<endl;
	deQueue(q);
	cout<<getFront(q)<<endl;
	return 0;
}
链队:
循环队列:
#include <bits/stdc++.h>
#define size 10
using namespace std;
//循环队列
typedef struct Queue {
	int data[size];
	int front, rear;
} Q;

void init(Q* q) {
	q->front=0;
	q->rear=0;
}

bool isEmpty(Q* q) {
	return q->rear==q->front;
}

bool isFull(Q* q) {
	return q->rear==size-1;
}

void enQueue(Q* q, int val) {
	if(isFull(q)) {
		return ;
	}
	q->data[q->rear]=val;
	q->rear=(q->rear+1)%size;
}

int deQueue(Q* q) {
	if(isEmpty(q)) {
		cout<<"empty queue!"<<endl;
		return -1;
	}
	int ans=q->data[q->front];
	q->front=(q->front+1)%size;
	return ans;
}

int getFront(Q* q) {
	if(isEmpty(q)) {
		cout<<"empty queue!"<<endl;
		return -1;
	}
	return q->data[q->front];
}

void clear(Q* q) {//clear()可以直接将队内元素出队,然后再delete队列q即可
	while(!isEmpty(q)) {
		deQueue(q);
	}
	delete q;
	q=nullptr;//删除q之后,防止再次调用q时引发内存问题
}

int main() {
	Q* q=new(Q);
	init(q);
	enQueue(q, 4);
	enQueue(q, 5);
	cout<<getFront(q)<<endl;
	deQueue(q);
	cout<<getFront(q)<<endl;
	clear(q);
	cout<<getFront(q);
	return 0;
}

第四章:堆

第五章:串

第六章:树

二叉树的前、中、后序遍历(递归版):
#include <bits/stdc++.h>
using namespace std;

typedef struct BinaryTree {
	char data;
	BinaryTree* lchild, * rchild;
} BT;

void create(BT** node) {
	char input;
	cin>>input;
	if(input=='#')
		*node=nullptr;
	else {
		*node=new(BT);
		(*node)->data=input;
		create(&(*node)->lchild);
		create(&(*node)->rchild);
	}
}

void preOrder(BT* root) {
	if(root==nullptr)
		return ;
	cout<<root->data<<" ";
	preOrder(root->lchild);
	preOrder(root->rchild);
}

void inOrder(BT* root) {
	if(root==nullptr)
		return ;
	inOrder(root->lchild);
	cout<<root->data<<" ";
	inOrder(root->rchild);
}

void posOrder(BT* root) {
	if(root==nullptr)
		return ;
	posOrder(root->lchild);
	posOrder(root->rchild);
	cout<<root->data<<" ";
}

int main() {
	BT* root;
	create(&root);
	preOrder(root);
	cout<<endl;
	inOrder(root);
	cout<<endl;
	posOrder(root);
	return 0;
}
//abd##e##cf##g##
二叉树的前、中、后序遍历(非递归版):
#include <bits/stdc++.h>
using namespace std;

typedef struct BinaryTree {
	char data;
	BinaryTree* lchild, * rchild;
} BT;

void create(BT** node) {//建立二叉树,按照中序的顺序建立结点
	char input;
	cin>>input;
	if(input=='#') {
		*node=nullptr;
	} else {
		*node=new(BT);
		(*node)->data=input;
		create(&(*node)->lchild);
		create(&(*node)->rchild);
	}
}



void preOrder(BT* root) {//前序遍历非递归
	stack<BT*> s;
	BT* curr;
	s.push(root);
	while(!s.empty()) {
		curr=s.top();
		s.pop();
		cout<<curr->data<<" ";
		if(curr->rchild!=nullptr) {//先入右儿子
			s.push(curr->rchild);
		}
		if(curr->lchild!=nullptr) {//再入左儿子
			s.push(curr->lchild);
		}
	}
}

void inOrder(BT* root) {//中序遍历非递归
	stack<BT*> s;
	BT* curr=root;
	while(!s.empty() || curr!=nullptr) {
		if(curr!=nullptr) {//将二叉树的左子树全部入栈
			s.push(curr);
			curr=curr->lchild;
		} else {//直到没有左子树就进行弹栈
			curr=s.top();
			s.pop();
			cout<<curr->data<<" ";//因为是中序遍历所以在弹栈后将curr指针跳到刚弹出的元素的右儿子上
			curr=curr->rchild;
		}
	}
}

void posOrder(BT* root) {
	stack<BT*> s;
	stack<BT*> collect;
	BT* curr;
	s.push(root);
	while(!s.empty()) {
		curr=s.top();
		s.pop();
		collect.push(curr);
		if(curr->lchild!=nullptr) {
			s.push(curr->lchild);
		}
		if(curr->rchild!=nullptr) {
			s.push(curr->rchild);
		}
	}
	while(!collect.empty()) {
		cout<<collect.top()->data<<" ";
		collect.pop();
	}
}
int main() {
	BT* root;
	create(&root);
	preOrder(root);
	cout<<endl;
	inOrder(root);
	cout<<endl;
	posOrder(root);
	return 0;
}
//abd##e##cf##g##
二叉树的层序遍历:
#include <bits/stdc++.h>
using namespace std;

typedef struct BinaryTree {
	char data;
	BinaryTree* lchild, * rchild;
} BT;

void create(BT** node) {
	char input;
	cin>>input;
	if(input=='#')
		*node=nullptr;
	else {
		*node=new(BT);
		(*node)->data=input;
		create(&(*node)->lchild);
		create(&(*node)->rchild);
	}
}

void levelOrder(BT* root) {//层序遍历
	queue<BT*> q;
	q.push(root);
	BT* curr;
	while(!q.empty()) {
		curr=q.front();
		q.pop();
		cout<<curr->data<<" ";
		if(curr->lchild!=nullptr) {
			q.push(curr->lchild);
		}
		if(curr->rchild!=nullptr) {
			q.push(curr->rchild);
		}
	}
}

int main() {
	BT* root;
	create(&root);
	levelOrder(root);
	return 0;
}
//abd##e##cf##g##
求二叉树的最大高度和最小高度:
#include <bits/stdc++.h>
using namespace std;

typedef struct Binary_tree {
	char data;
	Binary_tree* lchild, * rchild;
} BT;

void create(BT** node) {
	char input;
	cin>>input;
	if(input=='#') {
		*node=nullptr;
	} else {
		*node=new(BT);
		(*node)->data=input;
		create(&(*node)->lchild);
		create(&(*node)->rchild);
	}
}

//void levelOrder(BT* root) {
//	queue<BT*> q;
//	BT* curr=nullptr;
//	q.push(root);
//	while(!q.empty()) {
//		curr=q.front();
//		cout<<curr->data;
//		q.pop();
//		if(curr->lchild!=nullptr)
//			q.push(curr->lchild);
//		if(curr->rchild!=nullptr)
//			q.push(curr->rchild);
//	}
//}

int maxDepth(BT* root) {
	return root==nullptr? 0: max(maxDepth(root->lchild), maxDepth(root->rchild))+1;
}

int minDepth(BT* root) {
	//空树直接返回
	if(root==nullptr)
		return 0;
	//叶子节点
	if(root->lchild==nullptr && root->rchild==nullptr)
		return 1;
	int ldeep=65000;//左子树的高度设为极大数,代表还未查找
	int rdeep=65000;
	if(root->lchild!=nullptr)
		ldeep=minDepth(root->lchild);
	if(root->rchild!=nullptr)
		rdeep=minDepth(root->rchild);
	return min(ldeep, rdeep)+1;
}

int main() {
	BT* root;
	create(&root);
//	levelOrder(root);
	int deep=maxDepth(root);
	cout<<deep<<endl;
	deep=minDepth(root);
	cout<<deep;
	return 0;
}
//abd##e##c##
并查集://解决蓝桥杯国赛-合根植物24.4.29
#include <bits/stdc++.h>
#define ll long long
#define N 10005
using namespace std;
//并查集模板
//sample,需要改进
ll father[N], size[N], pre[N];

void init() {//初始化father数组,将每个数组的头都指向自己
	for(int i=0; i<N; i++) {
		father[i]=i;
	}
}

int find_(int i) {//寻找头
	if(father[i]==i) {//如果该点的头就是他自己,直接返回
		return i;
	}
	return father[i]=find_(father[i]);//否则递归查找头结点
}

bool sameRoot(int x, int y) {//判断x和y结点是不是在一个头上
	return find_(x)==find_(y);//调用fine_()进行判断,find_()会找到各自结点的最大头
}

void union_(int x, int y) {//将x和y结点连接在一个头上
	if(!sameRoot(x, y)) {//如果不在一个头上
		father[find_(x)]=find_(y);//用find_()找到x的最大头节点,随后连接到了y的头结点上
	}
}
int main() {
	
	return 0;
}

第七章:图

算法通关:

第一章:链表的经典算法

第二章:栈的经典算法

单调栈:
#include <bits/stdc++.h>
using namespace std;
//蓝桥杯_百亿富翁
stack<int> s;
int arr[5]= {3, 1, 2, 5, 4};
int ans[5];
int main() {
	for(int i=0; i<5; i++) {
		while(!s.empty() && arr[i]>=arr[s.top()]) {
			s.pop();
		}
		ans[i]=s.empty()? -1:s.top();
		s.push(i);
	}
	for(int i=0; i<5; i++) {
		cout<<ans[i]<<" ";
	}
	cout<<endl;

	while(!s.empty()) {
		s.pop();
	}
	memset(ans, 0, sizeof(ans));

	for(int i=4; i>=0; i--) {
		while(!s.empty() && arr[i]>=arr[s.top()]) {
			s.pop();
		}
		ans[i]=s.empty()? -1:s.top();
		s.push(i);
	}
	for(int i=0; i<5; i++) {
		cout<<ans[i]<<" ";
	}
	return 0;
}

第三章:队列的经典算法

第四章:堆的经典算法

第五章:串的经典算法

bf算法(brute force):
kmp算法:
#include <bits/stdc++.h>
#define N 20
using namespace std;

int nexta[N];
string s1="abababcc";
string s2="cc";

void getnext() {
	int len=s2.length();
	nexta[0]=-1, nexta[1]=0;
	int curr=2, cn=0;
	while(curr<len) {
		if(s2[curr-1]==s2[cn]) {
			nexta[curr++]=++cn;
		} else if(cn>0) {
			cn=nexta[cn];
		} else {
			nexta[curr++]=0;
		}
	}
}

int kmp() {
	int lenS1=s1.length();
	int lenS2=s2.length();
	int x=0, y=0;
	getnext();
	while(x<lenS1 && y<lenS2) {
		if(s1[x]==s2[y]) {
			x++, y++;
		} else if(y==0) {
			x++;
		} else {
			y=nexta[y];
		}
	}
	return y==lenS2 ? x-y : -1;
}
int main() {
	int ans=kmp();
	cout<<ans;
	return 0;
}

第六章:树的经典算法

第七章:图的经典算法

bfs(广度优先搜索):
迷宫问题:
#include <bits/stdc++.h>
#define N 4
using namespace std;

int maze[N][N]= { {0, 1, 1, 1}, {0, 0, 0, 0}, {1, 1, 1, 0}, {0, 0, 0, 0} };
int vis[N][N]={0};
pair<int, int> pre[N][N];
int dx[4]={0, 1, 0, -1};
int dy[4]={1, 0, -1, 0};
queue<pair<int, int>> q;
stack<pair<int, int>> s;
int startx=0, starty=0, endx=N-1, endy=N-1;

void bfs() {
	q.push({startx, starty});
	vis[startx][starty]=1;
	while(!q.empty()) {
		int x=q.front().first;
		int y=q.front().second;
		q.pop();
		if(x==endx && y==endy) {
			return ;
		}
		for(int i=0; i<4; i++) {
			int tx=dx[i]+x;
			int ty=dy[i]+y;
			if(tx>=0 && tx<N && ty>=0 && ty<N && maze[tx][ty]==0 && vis[tx][ty]==0) {
				q.push({tx, ty});
				vis[tx][ty]=1;
				pre[tx][ty]={x, y};
			}
		}
	}
}

void path() {
	int x=endx, y=endy;
	pair<int, int> curr;
	while(x!=startx || y!=starty) {
		s.push({x, y});
		curr=pre[x][y];
		x=curr.first;
		y=curr.second;
	}
	s.push({startx, starty});
	while(!s.empty()) {
		cout<<s.top().first<<","<<s.top().second<<endl;
		s.pop();
	}
}
int main() {
	bfs();
	path();
	return 0;
}
dfs(深度优先搜索):
迷宫问题:
#include <bits/stdc++.h>
#define N 4
using namespace std;
//dfs迷宫+路径回溯

int maze[N][N]={
	{0, 1, 1, 1},
	{0, 0, 0, 0},
	{1, 0, 0, 1},
	{1, 0, 0, 0}
};
int dx[4]={0, 1, 0, -1};
int dy[4]={1, 0, -1, 0};
int vis[N][N]={0};
int stx=0, sty=0, edx=N-1, edy=N-1;
int minStep=99;
stack<pair<int, int>> s;
pair<int, int> pre[N][N];

void dfs(int x, int y, int step) {
	
	if(x==edx && y==edy) {
		minStep=min(minStep, step);
		return ;
	}
	for(int i=0; i<4; i++) {
		int tx=dx[i]+x;
		int ty=dy[i]+y;
		if(tx>=0 && tx<N && ty>=0 && ty<N && maze[tx][ty]==0 && vis[tx][ty]==0) {
			vis[tx][ty]=1;
			pre[tx][ty]={x, y};
			dfs(tx, ty, step+1);
			vis[tx][ty]=0;
		}
	}
	return ;
}

void path() {
	int x=edx, y=edy;
	pair<int, int> curr;
	while(x!=stx || y!=sty) {
		s.push({x, y});
		curr=pre[x][y];
		x=pre[x][y].first;
		y=pre[x][y].second;
	}
	s.push({stx, sty});
	
	while(!s.empty()) {
		cout<<s.top().first<<","<<s.top().second<<endl;
		s.pop();
	}
}

int main() {
	dfs(0, 0, 0);
	cout<<minStep<<endl;
	path();
	return 0;
}

最小生成树:
Kruskal:
//https://www.luogu.com.cn/problem/P3366
#include <bits/stdc++.h>
#define M 200010
#define ll long long
using namespace std;
//Kruskal
int fa[M], edge[M][3];
ll n, m, x, y, z;

void build() {
	for (int i = 0; i < M; i++) {
		fa[i] = i;
	}
}

int find_(int i) {
	if (fa[i] == i)
		return i;
	return fa[i] = find_(fa[i]);
}

bool isSameRoot(int x, int y) {
	return find_(x) == find_(y);
}

bool union_(int x, int y) {
	if (!isSameRoot(x, y)) {
		fa[find_(x)] = find_(y);
		return true;
	}
	return false;
}

int cmp(const void* a, const void* b) {
	int* n1=(int* )a;
	int* n2=(int* )b;
	return n1[2]-n2[2];
}

int main() {
	build();
	cin>>n>>m;
	for(int i=0; i<m; i++) {
		cin>>x>>y>>z;
		edge[i][0]=x;
		edge[i][1]=y;
		edge[i][2]=z;
	}
	qsort(edge, m, sizeof(int[3]), cmp);
	
	int cnt=0, ans=0;
	
	for(int i=0; i<m; i++) {
		if(union_(edge[i][0], edge[i][1])) {
			cnt++;
			ans+=edge[i][2];
		}
	}
	
	cnt==n-1? cout<<ans: cout<<"orz";
	return 0;
}

拓展:其他算法

二分查找:

二分答案:
一维差分:
#include <bits/stdc++.h>
#define N 7
using namespace std;
//一维差分

//需要在数组实际数据的大小上额外开辟2个空间用于差分操作,实际数据从下标为1的地址上开始存储
int arr[N]={0, 2, 2, 2, 1, 5, 0};
int	diff[N]={0};

int main() {
	//加工差分数组
	for(int i=1; i<N; i++) {
		diff[i]=arr[i]-arr[i-1];
	}
	
	int times=2, l, r, x;
    //times:对数组进行加减操作的次数。
	while(times--) {
		cin>>l>>r>>x;
		diff[l]+=x;
		diff[r+1]-=x;
	}
	
	//求前缀和还原差分数组
	for(int i=1; i<N; i++) {
		diff[i]+=diff[i-1];
	}
	
	for(int i=1; i<N-1; i++) {
		cout<<diff[i]<<" ";
	}
	
	return 0;
}

动态规划(dp):
斐波那契数列:
#include <bits/stdc++.h>
#define N 20
using namespace std;
//dp_斐波那契数列

int dp[N];
int main() {
	dp[0]=0, dp[1]=1, dp[2]=1;
	for(int i=2; i<=N; i++) {
		dp[i]=dp[i-1]+dp[i-2];
	}
	for(int i=0; i<=N; i++) {
		cout<<dp[i]<<" ";
	}
	
	return 0;
}

 背包问题:
01背包:
#include <bits/stdc++.h> 
#define MAX 1001
using namespace std;
//蓝桥杯题库:小明的背包1
int w[MAX], v[MAX];
int N, V;
int dp[MAX+1][MAX+1]={0};//放在main()中间会因为空间不足而dead

int main() {
	cin>>N>>V;
	for(int i=1; i<=N; i++) {
		cin>>v[i]>>w[i];
	}
	
	for(int i=1; i<=N; i++) {
		for(int j=1; j<=V; j++) {
			if(j<v[i]) {//拿不下,背包空间小于当前物品的体积
				dp[i][j]=dp[i-1][j];
			} else {
				dp[i][j]=max(dp[i-1][j], dp[i-1][j-v[i]]+w[i]);
			}
		}
	}
	cout<<dp[N][V];
	return 0;
}
高精度算法:
高精度加法:
#include <bits/stdc++.h>
using namespace std;
//高精度加法
string s1, s2;
int num1[1000], num2[1000];
int main() {
	cin>>s1>>s2;
	reverse(s1.begin(), s1.end());
	reverse(s2.begin(), s2.end());
	int len1=s1.length(), len2=s2.length();
	for(int i=0; i<len1; i++) {
		num1[i]=s1[i]-'0';//得到数值
	}
	for(int i=0; i<len2; i++) {
		num2[i]=s2[i]-'0';
	}
	int size=max(len1, len2)+1;//多加一位,在进位时可以保证位数
//	cout<<size;
	int ans[size]={0}, carry=0;
	for(int i=0; i<max(len1, len2); i++) {
		ans[i]=num1[i]+num2[i]+carry;
		carry=ans[i]/10;
		ans[i]%=10;
	}
	if(carry>0) {//控制最高位,如果carry到最后都还>0则说明要向最高位进位,否则就将最高位不计入
		ans[size-1]=carry;
	} else {
		size--;
	}
	for(int i=size-1; i>=0; i--) {//反向打印数组
		cout<<ans[i];
	}
	return 0;
}
高精度减法:
#include <bits/stdc++.h>
using namespace std;
//高精度减法
string s1, s2;
int num1[1000], num2[1000];

bool cmp(string s1, string s2) {
	if (s1.length() < s2.length() || s1.length() == s2.length() && s1 < s2) {
		swap(s1, s2);
		return true;
	}
	return false;
}

int main() {
	cin >> s1 >> s2;
	bool flag = cmp(s1, s2);
//	cout<<s1<<endl<<s2;
	int len1 = s1.length(), len2 = s2.length();
	reverse(s1.begin(), s1.end()), reverse(s2.begin(), s2.end());
	for (int i = 0; i < len1; i++)
		num1[i] = s1[i] - '0';
	for (int i = 0; i < len2; i++)
		num2[i] = s2[i] - '0';


	int size = max(len1, len2);
	int ans[size];
	if (!flag) {
		for (int i = 0; i < size; i++) {
			if (num1[i] - num2[i] < 0) {
				num1[i + 1]--;
				num1[i] += 10;
			}
			ans[i] = num1[i] - num2[i];
		}
	} else {
		cout << "-";
		for (int i = 0; i < size; i++) {
			if (num2[i] - num1[i] < 0) {
				num2[i + 1]--;
				num2[i] += 10;
			}
			ans[i] = num2[i] - num1[i];
		}
	}
	while (ans[size - 1] == 0) {
		size--;
	}
	for (int i = size - 1; i >= 0; i--) {
		cout << ans[i];
	}
	return 0;
}
高精度乘法:
#include <bits/stdc++.h>
#define ll long long
using namespace std;

int main() {
    string a, b;
    cin >> a >> b;

    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());

    int lenA = a.length();
    int lenB = b.length();

    int A[2000], B[2000], C[2010] = {0}; // 初始化 C 数组

    for (int i = 0; i < lenA; i++) {
        A[i] = a[i] - '0';
    }
    for (int i = 0; i < lenB; i++) {
        B[i] = b[i] - '0';
    }
    int lenC = lenA + lenB;

    // 模拟乘法
    for (int i = 0; i < lenA; i++) {
        for (int j = 0; j < lenB; j++) {
            C[i + j] += A[i] * B[j]; // 这里修正为 C[i+j]
            C[i + j + 1] += C[i + j] / 10; // 处理进位
            C[i + j] %= 10; // 当前位
        }
    }

    // 处理结果长度
    while (lenC > 0 && C[lenC - 1] == 0) lenC--; // 去除前导零

    if (lenC == 0) cout << 0; // 如果结果为0
    else {
        for (int i = lenC - 1; i >= 0; i--) {
            cout << C[i];
        }
    }
    return 0;
}
前缀:
前缀树:

#include <bits/stdc++.h>
#define MAXN 15000
//前缀树
using namespace std;

int tree[MAXN][26];//a to z 26 letters
int end_[MAXN];//end在cpp是关键字
int pass[MAXN];
int cnt;

void build() {
	cnt = 1;
}

void insert(string word) {
	int curr = 1;
	pass[curr]++;
	for (int i = 0, path; i < word.size(); i++) {
		path = (char)word[i] - 'a';
		if (tree[curr][path] == 0) {
			tree[curr][path] = ++cnt;
		}
		curr = tree[curr][path];
		pass[curr]++;
	}
    end_[curr]++;
}

int search(string word) {//按照整个字符串查找
	int curr = 1;
	for (int i = 0, path; i < word.size(); i++) {
		path = (char)word[i] - 'a';
		if (tree[curr][path] == 0) {
			return 0;
		}
		curr = tree[curr][path];
	}
	return end_[curr];
}

int prefixNumber(string pre) {//按照前缀信息查找
	int curr=1;
	for(int i=0, path; i<pre.size(); i++) {
		path=(char)pre[i]-'a';
		if(tree[curr][path]==0) {
			return 0;
		}
		curr=tree[curr][path];
	}
	return pass[curr];
}

void delete_(string word) {
	if (search(word) > 0) {//如果没有这个字符串直接返回
		int curr = 1;
		for (int i = 0, path; i < word.size(); i++) {
			path = (char)word[i] - 'a';//找出字符串每个字符的路径
			if(--pass[tree[curr][path]]==0) {//找出对应路径后让--pass,减少路径信息
				tree[curr][path]=0;//如果某条路径信息删除后为0,那么直接断开后面的路径
				return ;
			}
			curr=tree[curr][path];
		}
		end_[curr]--;//找到最后的情况,使end_[]--
	}
}

int main() {
	build();
    int m;
    cin>>m;
    while(m--) {
        int op;
        string word;
        cin>>op>>word;
        switch (op) {
            case 1:
                insert(word);
                break;
            case 2:
                delete_(word);
                break;
            case 3:
                if(search(word))
                    cout<<"YES"<<endl;
                else
                    cout<<"NO"<<endl;
                break;
            case 4:
                cout<<prefixNumber(word)<<endl;
        }
    }
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值