一、栈 队列
链表
#include<iostream>
using namespace std;
template<class T>
class node{
public:
node<T> *next;
T data;
node(){
}
node(const T& item)
{
data=item;
next=NULL;
}
};
template<class T>
class line{
node<T> *head,*rear;
int size;
node<T> *pre,*cur;
int pos;
public:
line()
{//附加头节点
head=pre=new node<T>();
cur=rear=NULL;
}
~line()
{
while(head)
{
node<T> *p=head;
head=head->next;
delete p;
}
}
void insertAt( const T& item)
{
node<T> *p=new node<T>(item,NULL);
p->next=cur;
pre->next=p;
cur=p;
size++;
if(!rear) rear=p;
}
void insertAfter( const T& item)
{
node<T> *p=new node<T> (item,NULL);
if(!cur)
{
head->next=p;
rear=p;
}
else
{
p->next=cur->next;
cur->next=p;
if(!p->next) rear=p;
}
size++;
cur=p;
}
void deleteAt()
{
pre->next=cur->next;
pos--;
}
void deleteAfter()
{
cur->next=cur->next->next;
}
};
int main()
{
line<int> L;
return 0;
}
栈类
#include<iostream>
using namespace std;
class stack{
private:
int *data;
int data_top;
int maxsize;
public:
stack(int sz)
{
data=new int [sz];
maxsize=sz;
data_top=-1;
};
~stack()
{
delete data;
};
void push(int x);
void pop();
bool empty();
bool full();
int top();
void clear();
};
void stack::push(int x)
{
data[++data_top]=x;
}
void stack::pop()
{
data_top--;
}
bool stack::empty()
{
return data_top==-1;
}
bool stack::full()
{
return data_top==maxsize-1;
}
int stack::top()
{
return data[data_top];
}
void stack::clear()
{
data_top=-1;
}
int main()
{
stack q(10);
for(int i=1;i<=5;i++)
{
q.push(i);
}
for(int i=1;i<=5;i++)
{
cout<<q.top()<<endl;
q.pop();
}
q.clear();
q.push(10086);
cout<<q.top();
return 0;
}
栈链表实现
#include<iostream>
using namespace std;
template<class T>
class node{
public:
node<T> *next;
T data;
node(){
}
node(const T& item)
{
data=item;
next=NULL;
}
};
template<class T>
class stack{
node<T> *head;
int cnt;
public:
stack()
{
head=NULL;
cnt=0;
}
~stack()
{
while(head)
{
node<T> *p=head;
head=head->next;
delete p;
}
}
void clear()
{
while(head)
{
node<T> *p=head;
head=head->next;
delete p;
}
}
void push( const T& item)
{
node<T> *p=new node<T>(item);
p->next=head;
head=p;
cnt++;
}
void pop()
{
if(head!=NULL)
{
node<T> *p=head;
head=head->next;
delete p;
cnt--;
}
}
T top()
{
return head->data;
}
bool empty()
{
return head==NULL;
}
int size()
{
return cnt;
}
};
int main()
{
stack<int> q;
for(int i=1;i<=10;i++)
{
q.push(i);
}
cout<<q.top();
q.pop();
cout<<endl<<q.empty();
cout<<endl<<q.size();
q.clear();
while(!q.empty())
{
cout<<endl<<q.top();
q.pop();
}
return 0;
}
队列类
#include<iostream>
using namespace std;
class cQueue
{
private:
int head, rear, maxSize;
int *a;
public:
cQueue(int sz);
~cQueue() {delete a;}
bool empty();
bool full();
int size();
void push(int x);
int front();
void pop();//删除队头元素
};
cQueue::cQueue(int sz)
{ head = rear = 0; maxSize = sz;
a = new int[sz];
}
bool cQueue::empty()
{ return head==rear;
}
bool cQueue::full()
{ return head==(rear+1)%maxSize;
}
int cQueue::size()
{ return (rear - head + maxSize)%maxSize;
}
void cQueue::push(int x)
{ a[rear++] = x; rear %= maxSize; //cout<<size()<<endl;
}
int cQueue::front()
{ return a[head];
}
void cQueue::pop()
{ head++; head %= maxSize;
}
/*
//循环队列的正确性测试
int main()
{ cQueue q(100);
for(int i=1; i<=15; i++) //i<=15再测试一次
q.push(i);
while(q.size())
{ cout<<q.front()<<" ";
q.pop();
}
return 0;
}
*/
//求解舞伴问题
int main()
{ int man, lady, m; // 男士、女士的人数,舞曲数
cQueue qM(1000), qL(1000); // 男士、女士队列
cin>>man>>lady>>m;
for(int i=1; i<=man; i++) qM.push(i);
for(int i=1; i<=lady; i++) qL.push(i);
for(int i=1; i<=m; i++)
{ int a, b;
a = qM.front();
qM.pop();
qM.push(a);
b = qL.front();
qL.pop();
qL.push(b);
cout<<a<<" "<<b<<endl;
}
return 0;
}
队列链表实现
#include<iostream>
using namespace std;
template<class T>
class node{
public:
node<T> *next;
T data;
node(){
}
node(const T& item)
{
data=item;
next=NULL;
}
};
template<class T>
class queue{
node<T> *head;
node<T> *rear;
int cnt;
public:
queue()
{
head=NULL;
rear=NULL;
cnt=0;
}
~queue()
{
while(head)
{
node<T> *p=head;
head=head->next;
delete p;
}
}
void clear()
{
while(head)
{
node<T> *p=head;
head=head->next;
delete p;
}
}
void push( const T& item)
{
node<T> *p=new node<T>(item);
if (head==NULL)
{
head=rear=p;
cnt++;
}
else
{
rear->next=p;
rear=p;
cnt++;
}
}
void pop()
{
if(head!=NULL)
{
node<T> *p=head;
head=head->next;
delete p;
cnt--;
}
}
T top()
{
return head->data;
}
bool empty()
{
return head==NULL;
}
int size()
{
return cnt;
}
};
int main()
{
queue<int> q;
for(int i=1;i<=10;i++)
{
q.push(i);
}
cout<<q.top();
q.pop();
cout<<endl<<q.empty();
cout<<endl<<q.size();
q.clear();
while(!q.empty())
{
cout<<endl<<q.top();
q.pop();
}
return 0;
}
后缀表达式
#include<iostream>
#include<string>
using namespace std;
class stack{
private:
double *data;
int data_top;
int maxsize;
public:
stack(int sz)
{
data=new double [sz];
maxsize=sz;
data_top=-1;
};
~stack()
{
delete data;
};
void push(double x);
void pop();
bool empty();
bool full();
double top();
void clear();
};
void stack::push(double x)
{
data[++data_top]=x;
}
void stack::pop()
{
data_top--;
}
bool stack::empty()
{
return data_top==-1;
}
bool stack::full()
{
return data_top==maxsize-1;
}
double stack::top()
{
return data[data_top];
}
void stack::clear()
{
data_top=-1;
}
int main()
{
stack q(100);
string buf;
cin>>buf;
int i=0;
while (buf[i])
{
double x,y;
switch(buf[i]){
case '+':
x=q.top(); q.pop();
y=q.top(); q.pop();
q.push(x+y);
break;
case '-':
x=q.top(); q.pop();
y=q.top(); q.pop();
q.push(y-x);
break;
case '*':
x=q.top(); q.pop();
y=q.top(); q.pop();
q.push(x*y);
break;
case '/':
x=q.top(); q.pop();
y=q.top(); q.pop();
q.push(y/x);
break;
default:
q.push(double(buf[i]-'0'));
}
i++;
}
cout<<q.top()<<endl;
return 0;
}
中缀表达式
//保持运算符栈中的栈顶运算符在运算符中保持最高的运算级
#include<iostream>
#include<string>
using namespace std;
template<class T>
class stack{
private:
T *data;
int data_top;
int maxsize;
public:
stack(int sz)
{
data=new T [sz];
maxsize=sz;
data_top=-1;
};
~stack()
{
delete data;
};
void push(T x);
void pop();
bool empty();
bool full();
T top();
void clear();
};
template<class T>
void stack<T>::push(T x)
{
data[++data_top]=x;
}
template<class T>
void stack<T>::pop()
{
data_top--;
}
template<class T>
bool stack<T>::empty()
{
return data_top==-1;
}
template<class T>
bool stack<T>::full()
{
return data_top==maxsize-1;
}
template<class T>
T stack<T>::top()
{
return data[data_top];
}
template<class T>
void stack<T>::clear()
{
data_top=-1;
}
void compute(stack<char>& a, stack<double>& b)
{
char c=a.top();
a.pop();
double x=b.top();
b.pop();
double y=b.top();
b.pop();
switch (c)
{
case '+':
b.push(x+y);
break;
case '-':
b.push(y-x);
break;
case '*':
b.push(x*y);
break;
case '/':
b.push(y/x);
break;
}
}
int main()
{
stack<char> opsk(100);
stack<double> numsk(100);
string s;
cin>>s;
int i=0;
while(s[i])
{
if(s[i]>='0'&&s[i]<='9')
{
numsk.push(double(s[i]-'0'));
}
else if(opsk.empty()||s[i]=='(')
{
opsk.push(s[i]);
}
else if(s[i]==')')
{
while(opsk.top()!='(')
{
compute(opsk,numsk);
}
opsk.pop();
}
else if(s[i]=='*'||s[i]=='/')
{
while(opsk.top()=='*'||opsk.top()=='/')
compute(opsk,numsk);
opsk.push(s[i]);
}
else if(s[i]=='+'||s[i]=='-')
{
while(opsk.top()!='('&&!opsk.empty())
{
compute(opsk,numsk);
}
opsk.push(s[i]);
}
i++;
}
while(!opsk.empty())
{
compute(opsk,numsk);
}
cout<<numsk.top()<<endl;
return 0;
}
中缀转后缀表达式
//保持运算符栈中的栈顶运算符在运算符中保持最高的运算级
#include<iostream>
#include<string>
using namespace std;
template<class T>
class stack{
private:
T *data;
int data_top;
int maxsize;
public:
stack(int sz)
{
data=new T [sz];
maxsize=sz;
data_top=-1;
};
~stack()
{
delete data;
};
void push(T x);
void pop();
bool empty();
bool full();
T top();
void clear();
};
template<class T>
void stack<T>::push(T x)
{
data[++data_top]=x;
}
template<class T>
void stack<T>::pop()
{
data_top--;
}
template<class T>
bool stack<T>::empty()
{
return data_top==-1;
}
template<class T>
bool stack<T>::full()
{
return data_top==maxsize-1;
}
template<class T>
T stack<T>::top()
{
return data[data_top];
}
template<class T>
void stack<T>::clear()
{
data_top=-1;
}
string a;
void compute(stack<char>& b)
{
char c=b.top();
b.pop();
a+=c;
}
int main()
{
stack<char> opsk(100);
string s;
cin>>s;
int i=0;
while(s[i])
{
if(s[i]>='0'&&s[i]<='9')
{
a+=s[i];
}
else if(opsk.empty()||s[i]=='(')
{
opsk.push(s[i]);
}
else if(s[i]==')')
{
while(opsk.top()!='(')
{
compute(opsk);
}
opsk.pop();
}
else if(s[i]=='*'||s[i]=='/')
{
while(opsk.top()=='*'||opsk.top()=='/')
compute(opsk);
opsk.push(s[i]);
}
else if(s[i]=='+'||s[i]=='-')
{
while(opsk.top()!='('&&!opsk.empty())
{
compute(opsk);
}
opsk.push(s[i]);
}
i++;
}
while(!opsk.empty())
{
compute(opsk);
}
cout<<a<<endl;
return 0;
}
二、排序算法
插入排序
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
int n;
int a[10000000];
template <class T>
void sort(T *a,int n)
{
for(int i=0;i<n;i++)
{
T temp=a[i];
int p=i;
for(int j=i;j>=0;j--)
{
if(temp<a[j])
{
a[p]=a[j];
p=j;
}
else
{
break;
}
}
a[p]=temp;//如果是从i到0都没有比他大的在零号位就没有赋值,就会有问题,
//所以应该写在最后
}
}
int main()
{
srand(time(0));
double t=time(0);
cin>>n;
for(int i=0;i<n;i++)
{
//cin>>a[i];
a[i]=rand()%10000*rand()%10000;
}
sort(a,n);
/*for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}*/
cout<<time(0)-t;
return 0;
}
归并排序
#include<iostream>
using namespace std;
template <class T>
void TwoWayMerge(T Dst[],T Src[],int s,int e1,int e2)
{
int s1,s2;
for(s1=s,s2=e1+1;s1<=e1&&s2<=e2;)
{
if (Src[s1]<=Src[s2])
{
Dst[s++]=Src[s1++];
}
else
{
Dst[s++]=Src[s2++];
}
}
if(s1<=e1)
{
memcpy(&Dst[s],&Src[s1],(e1-s1+1)*sizeof(T));
}
else
{
memcpy(&Dst[s],&Src[s2],(e2-s2+1)*sizeof(T));
}
}
template <class T>
void OnePassMerge(T Dst[],T Src[],int len,int n)
{
int i;
for(i=0;i+2*len<n;i+=2*len)
TwoWayMerge(Dst,Src,i,i+len-1,i+2*len-1);
if(i<n-len)
TwoWayMerge(Dst,Src,i,i+len-1,n-1);
else
memcpy(&Dst[i],&Src[i],(n-i)*sizeof(T));
}
template <class T>
void Mergesort(T Src[],int n)
{
T *dst=new T[n];
int k=1;
while(k<n)
{
OnePassMerge(dst,Src,k,n);
k<<=1;
if(k>=n)
{
memcpy(Src,dst,n*sizeof(T));
}
else
{
OnePassMerge(Src,dst,k,n);
k<<=1;
}
}
delete [] dst;
}
int main()
{
int Src[8]={8,9,10,1,2,3,13,14};
Mergesort(Src,8);
for(int i=0;i<=7;i++)
{
cout<<Src[i]<<" ";
}
return 0;
}
基数排序
#include<iostream>
#include<queue>
using namespace std;
int maxdigit(int data[],int n)
{
int d=1;//计算最高位数
int p=10;//倍数
for(int i=0;i<n;i++)
{
while(data[i] >= p)
{
p*=10;
++d;
}
}
return d;
}
void radixsort(int data[],int n)
{
int digits=maxdigit(data,n);
queue<int> q[10];
int d,factor;
for(d=1,factor=1;d<=digits; factor*=10,d++)
{
for(int j=0;j<n;j++)
{
q[(data[j]/factor)%10].push(data[j]);
}
int j=0;
for(int k=0;k<10;k++)
{
while(!q[k].empty())
{
data[j++]=q[k].front();
q[k].pop();
}
}
}
}
int main()
{
int data[10] = {179, 208, 306, 93, 859, 984, 55, 9, 271, 33};
radixsort(data, 10);
cout << "排序后结果:" << endl;
for (int i = 0; i < 10; i++)
cout << data[i] << " ";
return 0;
}
快速排序
#include<iostream>
using namespace std;
int sort(int *a,int low,int high)
{
if(low<high)
{
int i=low;
int j=high;
int key=a[i];
while(i<j)
{
while(i<j&&a[j]>=key)
{
j--;
}
if(i<j)
{
a[i]=a[j];
i++;
}
while(i<j&&a[i]<=key)
{
i++;
}
if(i<j)
{
a[j]=a[i];
j--;
}
}
a[i]=key;
/*
//测试
cout<<key<<endl;
for(int i=0;i<=6;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;*/
sort(a,low,i-1);
sort(a,i+1,high);
}
}
int main()
{
int a[10]={5,8,99,44,55,1,-1};
sort(a,0,6);
for(int i=0;i<=6;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
冒泡排序
#include<iostream>
using namespace std;
const int maxn=1e5+3;
int a[maxn];
int n;
template <class T>
void sort(T *a,int n)
{
bool flag=true;
for(int i=0;i<n&&flag;i++)
{
flag=false;
for(int j=i+1;j<n;j++)
{
int temp=a[i];
if(a[i]>a[j])
{
flag=true;
a[i]=a[j];
a[j]=temp;
}
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,n);
for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
树形选择排序
#include<bits/stdc++.h>
using namespace std;
//树形排序:从小到大
template<class T>
void treeSort(T* a, int n)
{
#define Left(i) (2*(i)-2*n)
#define Right(i) (2*(i)-2*n+1)
#define Father(i) (n+(i)/2)
#define Brother(i) ((i)&1?(i)-1:(i)+1)
#define Root (2*n-2)
#define min(a,b) (a)<(b)?(a):(b)
#define INF_VALUE 0x3FFFFFFF
T* t = new T(2*n-1);
memcpy(t, a, sizeof(T)*n);
//第1轮选择
for(int i=n; i<=Root; i++)
t[i]= min(t[Left(i)],t[Right(i)]);
a[0]=t[Root];
//第2轮至第n轮选择
for(int k=1; k<=n-1; k++)
{ // 将上一轮的最小值修改为无穷大INF_VALUE。
// 沿着等于t[Root]的分枝向下直到叶结点t[sel]=t[Root]
int sel=Root;
int left=Left(sel);
while(left>=0) // 判断sel是否为叶节点
{ sel = (t[sel]==t[left]) ? left : (left+1);
left=Left(sel);
}
t[sel]=INF_VALUE;
// 本轮选择:从叶往根从t[sel]往t[Root]选择最小值
sel=Father(sel);
while(sel<=Root)
{ t[sel] = min(t[Left(sel)],t[Right(sel)]);
sel = Father(sel);
}
a[k]=t[Root];
}
delete t;
}
int main()
{
int a[10]={0,45,723,23,3,45,5,8,9,12345};
treeSort(a, 10);
for(int i=0; i<10; i++)
cout<<a[i]<<" ";
return 0;
}
希尔排序
//希尔排序
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
const int maxn=1e7+3;
int a[maxn];
int n;
template <class T>
void ShellSort(T A[ ], int n, int s) //s分组数量
{ int i,j,k;
T temp;
for(k=s; k>0; k>>=1) //分组次数
for(i=k; i<n; i++)
//对A[i]所在组的前面部分插入排序
{
temp=A[i];
j=i-k;
while(j>=0 && temp<A[j])
//前面元素已经有序,第2个条件避免无效比较
{ A[j+k]=A[j]; j-=k; }
A[j+k]=temp;
}
}
int main()
{
srand(time(0));
double t=time(0);
cin>>n;
for(int i=0;i<n;i++)
{
// cin>>a[i];
a[i]=rand()%10000*rand()%10000;
}
ShellSort(a,n,n/2);
/*for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}*/
cout<<time(0)-t;
return 0;
}
二分查找优化插入排序
//递归二分方法优化插入排序
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
const int maxn=1e7+3;
int a[maxn];
int n;
int bins(int *a,int n,int l, int r,int i)//i为要插入的数据
{
if(l>r) return l;
int m=(l+r)/2;
if(a[i]<a[m])
return bins(a,n,l,m-1,i);
else
return bins(a,n,m+1,r,i);
}
void binssort(int *a,int n)
{
int k;//k为要插入的位置
for(int i=1;i<n;i++)
{
k=bins(a,n,0,i-1,i);
int temp=a[i];
for(int j=i;j>k;j--)
{
a[j]=a[j-1];
}
a[k]=temp;
}
}
void bbinssort(int *a,int n)
{
int i, k, r;
for (i=1; i<n; i++) //将a[i]插入a[0..i-1]
{ int temp=a[i]; k=0; r=i-1;
while (k<=r) //计算插入位置k
{ int m=(k+r)/2;
if (temp<a[m]) r=m-1;
else k=m+1;
}
for (r=i; r>k; r--) //移动a[k..i-1]至a[k+1..i]
a[r]=a[r-1];
a[k]=temp; //完成插入
}
}
int main()
{
srand(time(0));
double t=time(0);
//double t_clock=clock();
cin>>n;
for(int i=0;i<n;i++)
{
// cin>>a[i];
a[i]=rand()%10000*rand()%10000;
}
bbinssort(a,n);
/*for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}*/
cout<<time(0)-t<<endl;
//cout<<clock()-t_clock<<endl;
return 0;
}
三、查找算法
朴素查找
#include<bits/stdc++.h>
using namespace std;
char s[1000];
char p[1000];
int area[100];
int space;
void findarea(char* s,char *p)
{
int m=strlen(p);
int n=strlen(s);
for(int i=1;m+i-2<=n-1;i++)
{
int vis=0;
for(int j=0;j<m;j++)
{
if(s[i-1+j]!=p[j])
{
vis=1;
break;
}
}
if(vis==0)
{
area[++space]=i;
}
}
}
int main()
{
cin>>s>>p;
findarea(s,p);
if(!space)
{
cout<<"没有匹配的";
return 0;
}
for(int i=1;i<=space;i++)
{
cout<<area[i]<<" ";
}
return 0;
}
分块查找
//分块查找 块间有序 块内无序 包含索引项 包括最大关键码值和块的起始地址
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// 定义每个块的大小
const int blockSize = 3;
// 分块查找算法
int blockSearch(vector<int>& arr, vector<int>& blocks, int target) {
int n = arr.size();
int m = blocks.size();
// 先在块索引中查找
int blockIndex = -1;
for (int i = 0; i < m; i++) {
if (blocks[i] >= target) {
blockIndex = i;
break;
}
}
// 如果块索引中不存在,则返回-1
if (blockIndex == -1) {
return -1;
}
// 在对应的块中查找
int start = blockIndex * blockSize;
int end = min(start + blockSize, n);
for (int i = start; i < end; i++) {
if (arr[i] == target) {
return i;
}
}
// 如果块中不存在,则返回-1
return -1;
}
int main() {
vector<int> arr = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
int n = arr.size();
// 计算块的数量
int m = ceil(sqrt(n));
// 构建块索引
vector<int> blocks(m);
for (int i = 0; i < m; i++) {
blocks[i] = arr[i * blockSize];
}
int target = 6;
int index = blockSearch(arr, blocks, target);
if (index != -1) {
cout << "找到了,下标为:" << index << endl;
} else {
cout << "未找到" << endl;
}
return 0;
}
KMP算法
/*核心是next的求法,第0个数是-1 来控制j向后移动,第1个数是0 因为不会存在重复的字符子串
之后的数是他前面的最大重复子串的长度*/
#include<iostream>
#include<cstring>
using namespace std;
int nextt[100];
char T[1000], P[1000];
bool isSame(char *p, int s, int e)
//判断p[0: ]与p[s:e]是否相同
{ for(int k=0,i=s; i<=e; k++,i++)
if(p[k]!=p[i]) return 0;
return 1;
}
void genNext(char *p, int *nextt)
//用朴素方法求nextt[]
{
nextt[0] = -1;
nextt[1] = 0;
for(int i=2; i<strlen(p); i++)//cal nextt[i]
{
nextt[i] = 0;
for(int j=i-1; j>0; j--) //j: 相同前(后)缀的长度
{
if(isSame(p, i-j, i-1))
{
nextt[i] = j;
break;
}
}
if(p[nextt[i]]==p[i])//优化
{
nextt[i]=nextt[nextt[i]];
}
}
}
int main()
{
cin>>P>>T;
genNext(P, nextt);//计算nextt[ ]
for(int i=0;i<strlen(P);i++)
{
cout<<nextt[i]<<" ";
}
cout<<endl;
int i, j; //i:模式串P的下标 j:母串T的下标
for(i=0, j=0; i<strlen(P) && j<strlen(T); )
{
if(P[i]==T[j])//匹配则继续比较下一个字符
{
i++;
j++;
}
else if(nextt[i]>0)
{
i = nextt[i];
}
else
{
i=0;
j++;
}
}
if(i>=strlen(P)) cout<<j-strlen(P)<<endl;//首次匹配位置
else cout<<-1<<endl;
}
//输入样例1:ababacb
//输出样例1:-1 0 0 1 2 3 0
//输入样例2:abcabcd
//输出样例2:-1 0 0 0 1 2 3
//输入样例3:abcabca
//输出样例3:-1 0 0 0 1 2 3
/*ABABC
ABABC ABABCABAA CAADB ABABCAADKDABC*/
KMP优化
#include<iostream>
#include<string>
using namespace std;
#define next nex
string P,T;
int next[1000];
void Next(const string &P,int *next)
{
next[0]=-1;
int j=0;
int k=-1;
while(j<P.length()-1)
{
/* */
if(k==-1||P[j]==P[k])
{
j++;
k++;
next[j]=k;
}
/*next优化
if (k==-1||P[j]==P[k])
{
j++;
k++;
if(P[j]==P[k])
next[j]=next[k];
else
next[j]=k;
}*/
else
{
k=next[k];
}
}
}
void KMP(const string &P,const string& S)//P是模式串 S是文本串
{
int i=0,j=0;
Next(P,next);
for(int i=0;i<P.size();i++)
cout<<next[i]<<" ";
cout<<endl;
while(i<int(P.size())&&j<int (S.size()))//p.size()默认是unsigned类型
{
if(i==-1||P[i]==S[j])
{
i++;
j++;
}
else
{
i=next[i];
}
if(i==P.size())
{
cout<<j-P.size()<<" ";
i=next[i];
}
}
}
int main()
{
cin>>P>>T;
KMP(P,T);
return 0;
}
/*
ABABC
ABABCABABCABAACAADBABABCAADKDABC
*/
四、树
堆
#include<iostream>
#include<vector>
using namespace std;
void heapify(vector<int>& arr, int n, int i) {
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < n && arr[l] > arr[largest]) {
largest = l;
}
if (r < n && arr[r] > arr[largest]) {
largest = r;
}
if (largest != i) {
swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
void treeSelectionSort(vector<int>& arr) {
int n = arr.size();
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
for (int i = n - 1; i > 0; i--) {
swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
int main()
{
vector<int>a;
a={1,2,5,9,55};
treeSelectionSort(a);
for(int i=0;i<5;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
二叉树
#include<iostream>
using namespace std;
struct node{
int data;
node * pl,*pr;
}tree[20000];
int n;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
int a,l,r;
cin>>a>>l>>r;
tree[a].data=a;
if(!l) tree[a].pl=NULL;
else tree[a].pl=&tree[l];
if(!r) tree[a].pr=NULL;
else tree[a].pr=&tree[r];
}
node *p=&tree[1];
while(p)
{
cout<<p->data<<" ";
if(p->pl!=NULL)
{
p=p->pl;
}
else
{
p=p->pr;
}
}
return 0;
}
二叉树前中后序遍历
#include<iostream>
using namespace std;
struct node{
char data;
node * pl,*pr;
}tree[20000];
int n;
void preorder(node *t)
{
if(!t) return ;
cout<<t->data<<" ";
preorder(t->pl);
preorder(t->pr);
}
void inorder(node *t)
{
if(!t) return ;
inorder(t->pl);
cout<<t->data<<" ";
inorder(t->pr);
}
void endorder(node *t)
{
if(!t) return ;
endorder(t->pl);
endorder(t->pr);
cout<<t->data<<" ";
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
int l,r,idex;
char a;
cin>>idex>>a>>l>>r;
tree[idex].data=a;
if(!l) tree[idex].pl=NULL;
else tree[idex].pl=&tree[l];
if(!r) tree[idex].pr=NULL;
else tree[idex].pr=&tree[r];
}
cout<<"前序遍历: ";
preorder(&tree[1]);cout<<endl;
cout<<"中序遍历: ";
inorder(&tree[1]);cout<<endl;
cout<<"后序遍历: ";
endorder(&tree[1]);cout<<endl;
return 0;
}
二叉树层序遍历
#include<iostream>
#include<queue>
using namespace std;
struct node{
char data;
node * pl,*pr;
}tree[20000];
int n;
queue<node*>q;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
int l,r,idex;
char a;
cin>>idex>>a>>l>>r;
tree[idex].data=a;
if(!l) tree[idex].pl=NULL;
else tree[idex].pl=&tree[l];
if(!r) tree[idex].pr=NULL;
else tree[idex].pr=&tree[r];
}
node *p=&tree[1];
q.push(p);
while(!q.empty())
{
node *p=q.front();
cout<<p->data<<" ";
if(p->pl)
q.push(p->pl);
if(p->pr)
q.push(p->pr);
q.pop();
}
return 0;
}
/* 4
1 A 2 3
2 B 0 5
3 C 0 0
5 E 0 0 */
二叉排序树
//二叉排序树 左子树都小于根 右子树都大于根 新插入的节点一定是叶子节点
//删除操作 如果进行直接替换 ,替换的前驱(后继)不一定是叶子节点,可能有左子树(右子树)
// 如果是让后继变为前驱的右子树(前驱变为后继的左子树)要判断P的父节点是不是根节点
#include<iostream>
using namespace std;
template <class T>
class tNode {
public:
tNode<T>* left;
tNode<T>* right;
T data;
};
template <class T>
void freeTree(tNode<T>* root)
{
if(root)
{
freeTree(root->left);
freeTree(root->right);
delete root;
}
}
template <class T>
void insert(tNode<int>*& root, T x)
{
if (!root)
{
root = new tNode<T>;
root->left = root->right = NULL;
root->data = x;
return;
}
if (x < root->data)
insert(root->left, x);
else
insert(root->right, x);
}
template <class T>
bool findtnode ( tNode<int>* root, T x)
{
tNode<T>* cur = root;
while (cur)
{
if (cur->data == x)
{
return 1;
}
else if (cur->data < x)
{
cur = cur->right;
}
else
{
cur = cur->left;
}
}
return 0;
}
void firstroot(tNode<int>* root)
{
if (!root) return;
cout << root->data << " ";
firstroot(root->left);
firstroot(root->right);
}
void inroot(tNode<int>* root)
{
if (!root) return;
inroot(root->left);
cout << root->data << " ";
inroot(root->right);
}
tNode<int>* root;
int n;
int main()
{
cin >> n;
root = NULL;
for (int i = 1; i <= n; i++)
{
int a;
cin >> a;
insert(root, a);
}
firstroot(root);
cout << endl;
inroot(root);
return 0;
}
/*
9
7 4 2 6 17 11 13 8 9
*/
树变二叉树
//孩子兄弟表示法 树变二叉树
//x第一个孩子是x左孩子 x的兄弟是他的右儿子
//树的后序是二叉树的中序
//树的前序是二叉树的前序
#include<bits/stdc++.h>
using namespace std;
/*
输入一棵树,构造该树对应的二叉树,并输出二叉树的层序
遍历结果。
【输入格式】
节点数
节点的编号 子结点个数 各子结点编号
【输出格式】
先根遍历序列
后根遍历序列
*/
const int dMax = 5;
template<class T>
struct tNode
{ T data;
tNode *p[dMax];
};
const int MAXSIZE = 20000;
tNode<int> tree[MAXSIZE];
int N;
template<class T> //二叉树节点
struct bNode
{ T data;
bNode *L, *R;
};
bNode<int> *bTree; //二叉树
template<class T>
void createBTree(tNode<T> *tP, bNode<T> *& bP)
{ if(!tP) return;
bP = new bNode<T>;
bP->data = tP->data;
bP->L = bP->R = NULL;
//tP的第一个孩子成为节点bP的左孩子
if(!tP->p[0]) return;
createBTree(tP->p[0], bP->L);
//tP的其余孩子成为节点bP的左孩子的右孩子、
//左孩子的右孩子的右孩子、...
bNode<T> *tmp = bP->L;
for(int i=1; i<dMax; i++)
{ if(!tP->p[i]) return;
createBTree(tP->p[i], tmp->R);
tmp = tmp->R;
}
// bNode<T> *tmp = bP->L->R;//这么是错的,参数传递不正确!
// for(int i=1; i<dMax; i++)
// { if(!tP->p[i]) return;
// createBTree(tP->p[i], tmp);
// tmp = tmp->R;
// }
}
template<class T>
void levelOrder(bNode<T> *p)
{
}
template<class T>
void preOrder(bNode<T> *p)
{ if (!p) return;
cout<<p->data<<" ";
preOrder(p->L);
preOrder(p->R);
}
template<class T>
void postOrder(bNode<T> *p)
{ if (!p) return;
postOrder(p->L);
postOrder(p->R);
cout<<p->data<<" ";
}
int main()
{ int a, c, id;
//构建树
cin>>N;
for(int i=0; i<N; i++)
{ cin>>a>>c;
tree[a].data = a;
for(int j=0; j<c; j++)
{ cin>>id;
tree[a].p[j] = &tree[id];
}
}
createBTree(&tree[1], bTree);
cout<<"先序序列:";
preOrder(bTree); cout<<endl;
cout<<"后序序列:";
postOrder(bTree); cout<<endl;
return 1;
}
/*
输入样例1:
12
1 3 2 12 3
2 3 4 6 8
3 2 9 11
4 0
5 0
6 2 5 7
7 0
8 0
9 1 10
10 0
11 0
12 0
输出样例1;
1 2 4 6 5 7 8 12 3 9 10 11
4 5 7 6 8 2 12 10 9 11 3 1
*/
五、图
邻接表
#include<iostream>
using namespace std;
const int maxn=1e3;
int cin_g[maxn][maxn];
int n;
struct node{
node *next;
int val;
int id;
}v[maxn];
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
v[i].next=NULL;
for(int j=0;j<n;j++)
{
cin>>cin_g[i][j];
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(cin_g[i][j]>0)
{
node* va=new node;
va->val=cin_g[i][j];
va->next=NULL;
va->id=j;
if(!v[i].next)v[i].next=va;
else
{
node* p=new node;
p=v[i].next;
while(p)
{
if(!p->next)
{
p->next=va;
break;
}
else p=p->next;
}
}
}
}
}
for(int i=0;i<n;i++)
{
node* pp=v[i].next;
while(pp)
{
cout<<i<<"->"<<pp->id<<"权值是"<<pp->val<<" ";
pp= pp->next;
}
cout<<endl;
}
return 0;
}
/*
3
1 0 1
5 2 0
4 5 6
*/
简洁版邻接表
#include<iostream>
#define next nex
using namespace std;
const int maxn=1000001;
int first[maxn],next[maxn<<1],to[maxn<<1],val[maxn<<1],tot;
int n,m;
void add(int x,int y,int z)
{
next[++tot]=first[x];
first[x]=tot;
to[tot]=y;
val[tot]=z;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
add(x,y,1);
}
for(int e=first[2];e;e=next[e])
{
cout<<2<<"->"<<to[e]<<endl;
}
return 0;
}
/*
6 5
1 2
2 3
2 4
2 5
1 6
*/
/*
#include<iostream>
using namespace std;
#define next nex
const int maxn=1001;
int first[maxn],next[maxn<<1],to[maxn<<1],val[maxn<<1];
int tot;
void add(int x,int y,int z)
{
next[++tot]=first[x];
first[x]=tot;
to[tot]=y;
val[tot]=z;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
add(y,x,z);
}
for(int i=1;i<=n;i++)
{
for(int e=first[i];e;e=next[e])
{
int v=to[e];
int d=val[e];
cout<<v<<" "<<d<<" "<<endl;
}
}
}
*/
连接多重表
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
int n, m;
struct Edge {
bool vis;
char i;
int ilink;
char j;
int jlink;
}edge[103];
struct Node {
char dataa;
int pos;
}node_firstpos[12];
void insert(char x, char y, int pos)
{
edge[pos].vis = false;
edge[pos].i = x;
edge[pos].j = y;
edge[pos].ilink = 0;
edge[pos].jlink = 0;
for (int i = 1; i <= n; i++)
{
if (node_firstpos[i].dataa == x || node_firstpos[i].dataa == y)
{
int tmp = node_firstpos[i].pos;
int tmp_dataa = node_firstpos[i].dataa;
if (tmp == 0)
{
node_firstpos[i].pos = pos;
}
else {
int tm = 0;
while (tmp != 0)
{
tm = tmp;
if (edge[tmp].i == tmp_dataa)
{
tmp = edge[tmp].ilink;
}
else {
tmp = edge[tmp].jlink;
}
}
if (edge[tm].i == tmp_dataa)
{
edge[tm].ilink = pos;
}
else {
edge[tm].jlink = pos;
}
}
}
}
}
void pri()
{
for (int i = 1; i <= m; i++)
{
cout << edge[i].i << " " << edge[i].ilink << " " << edge[i].j << " " << edge[i].jlink << endl;
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
char da;
cin >> da;
node_firstpos[i].dataa = da;
node_firstpos[i].pos = 0;
}
cin >> m;
for (int i = 1; i <= m; i++)
{
char x, y;
cin >> x >> y;
insert(x, y, i);
}
pri();
return 0;
}
/*
5
A B C D E
6
A B
A C
C B
C E
D B
C D
*/
宽度优先遍历
#include<iostream>
#include<queue>
using namespace std;
#define next nex
const int maxn=1e3+1;
int tot,first[maxn],next[maxn<<1],to[maxn<<1],val[maxn<<1];
int vis[maxn];
void graph(int x,int y,int z)
{
next[++tot]=first[x];
first[x]=tot;
to[tot]=y;
val[tot]=z;
}
queue<int>q;
int m;
int main()
{
cin>>m;
for(int i=1;i<=m;i++)
{
char x,y;
cin>>x>>y;
graph(x-'A',y-'A',1);
}
q.push(0);
vis[0]=1;
while(!q.empty())
{
int i=q.front();
q.pop();
cout<<char(i+'A')<<" ";
for(int e=first[i];e;e=next[e])
{
if(vis[to[e]]==0)
{
q.push(to[e]);
vis[to[e]]=1;
}
}
}
return 0;
}
/*
编程实现无向图的宽度优先遍历。顶点用大写字母表示。
假设从顶点A开始搜索。
#include<bits/stdc++.h>
using namespace std;
const int MAXSIZE = 200;
bool G[MAXSIZE][MAXSIZE], B[MAXSIZE];
int N; //边的数量
int main()
{ char x, y;
cin>>N;
for(int i=1; i<=N; i++)
{ cin>>x>>y;
G[x][y] = G[y][x] = 1;
}
//广搜
queue<char> q;
q.push('A'); B['A'] = 1;
while(q.size())
{ char x = q.front();
q.pop();
cout<<x<<" ";
for(int i='A'; i<='Z'; i++)
{ if(!G[x][i]) continue;//边(x,i)不存在
if(B[i]) continue;//顶点i已经被访问
q.push(i);
B[i] = 1;
}
}
return 0;
}
*/
/*
【输入样例1】
7
A B
A F
A C
B F
B D
D C
E F
【输出样例1】
A B C F D E
【输入样例2】
9
A B
A C
A E
B D
B E
C E
D E
E F
F C
【输出样例2】
A B C E D F
*/
深度优先遍历
#include<iostream>
#include<queue>
using namespace std;
#define next nex
const int maxn=1e3+1;
int tot,first[maxn],next[maxn<<1],to[maxn<<1],val[maxn<<1];
int vis[maxn];
void graph(int x,int y,int z)
{
next[++tot]=first[x];
first[x]=tot;
to[tot]=y;
val[tot]=z;
}
void dfs(int x)
{
cout<<char(x+'A')<<" ";
vis[x]=1;
for(int e=first[x];e;e=next[e])
{
int u=to[e];
if(!vis[u])
{
dfs(u);
}
}
}
int m;
int main()
{
cin>>m;
for(int i=1;i<=m;i++)
{
char x,y;
cin>>x>>y;
graph(x-'A',y-'A',1);
}
dfs(0);
return 0;
}
/*
编程实现有向图的深度优先遍历。顶点用大写字母表示。
#include<bits/stdc++.h>
using namespace std;
const int MAXSIZE = 200;
bool G[MAXSIZE][MAXSIZE], B[MAXSIZE];
int N; //边的数量
void dfs(char x)
{ cout<<x<<" ";
B[x] = 1;
for(int i='A'; i<='Z'; i++)
{ if(!G[x][i]) continue;//边(x,i)不存在
if(B[i]) continue;//顶点i已经被访问
dfs(i);
//B[i] = 1;
}
}
int main()
{ char x, y;
cin>>N;
for(int i=1; i<=N; i++)
{ cin>>x>>y;
G[x][y] = 1;
}
//深搜
dfs('A');
return 0;
}
/*
【输入样例1】
9
A B
A C
A E
B D
B E
C E
D E
E F
F C
【输出样例1】
A B D E F C
【输入样例2】
7
A B
A F
A C
B F
B D
D C
E F
【输出样例2】
A B D C F //注意:E搜不到 要想搜到E,还需要增加检查代码
*/
最小生成树克鲁斯卡尔
#include<bits/stdc++.h>
using namespace std;
const int maxn=200005;
const int point=5003;
int ans,n,m;
int f[maxn];
struct node{
int x;
int y;
int val;
}g[maxn];
int find(int x)
{
if(f[x]==x)
{
return x;
}
else return f[x]=find(f[x]);
}
int cmp(node &a,node &b)
{
return a.val <b.val ;
}
void kruskal()
{
int k=0;
for(int i=1;i<=m;i++)
{
int v=g[i].x ;
int u=g[i].y ;
int a=find(v);
int b=find(u);
if(a!=b)
{
f[a]=b;
ans+=g[i].val ;
k++;
}
if(k==n-1)
break;
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>g[i].x>>g[i].y>>g[i].val;
}
for(int i=1;i<=n;i++)
{
f[i]=i;
}
sort(g+1,g+m+1,cmp);
kruskal();
cout<<ans<<endl;
return 0;
}
最小生成树prim
//将所有点分为两个集合 一个集合为最小生成树里面的,另一个是没有选中的。
//选一个点放树里,看他到另一个集合的最短的边,将那个点更新到树里
#include<iostream>
#include<cstring>
using namespace std;
#define next nex
const int maxn=200005;
const int point=5003;
int first[point],next[maxn<<1],to[maxn<<1],val[maxn<<1],tot;
int n,m,res;
void add(int x,int y,int z)
{
next[++tot]=first[x];
first[x]=tot;
to[tot]=y;
val[tot]=z;
}
struct node{
int pre;
int weight;
}dis[maxn];
int vis[maxn];
void prim()
{
dis[1].weight=0;
dis[1].pre=1;
for(int i=1;i<=n;i++)
{
int ans=1e9;
int k;
for(int j=1;j<=n;j++)
{
if(vis[j]==0&&dis[j].weight<ans)
ans=dis[j].weight,k=j;
}
vis[k]=1;
if (k!=1)cout<<dis[k].pre<<" "<<k<<" "<<endl;
for(int e=first[k];e;e=next[e])
{
int u=to[e];
if(vis[u]==0&&dis[u].weight>val[e])
{
dis[u].weight=val[e];
dis[u].pre=k;
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
add(y,x,z);
}
memset(dis,0x7f,sizeof(dis));
prim();
cout<<endl;
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
cout<<"orz"<<endl;return 0;
}
else
res+=dis[i].weight;
}
cout<<res<<endl;
return 0;
}
/* Prim算法
输入一个带权图,构造其最小生成树。依次输出每一次选中的边。
【输入格式】
n(顶点数)
e(边数)
以下e行,每行3个数i,j,wij,表示在顶点i,j之间的权值
*/
/*
#include<bits/stdc++.h>
using namespace std;
int g[101][101];// 邻接矩阵
int minn[101]; // minn[i]存放蓝点i与白点相连的最小边权
int pre[101]; // pre[i]记录点i的minn[i]对应的连接点
bool b[101]; // b[i]=false,表示i是蓝点
int n, e;
int main()
{ int x, y, w, k;
memset(minn, 0x7f, sizeof(minn)); //初始化为maxint
minn[1] = 0; pre[1] = 0;//首先选择顶点1
cin>>n>>e;
for(int i=1; i<=e; i++)
{ cin>>x>>y>>w;
g[x][y]=g[y][x]=w;
}
for(int i=1; i<=n; i++)//一共n个顶点,顶点1肯定首先选中
{ k = 0;
for(int j=1; j<=n; j++) //找minn[]最小的蓝点k
if(!b[j] && (minn[j]<minn[k]))
k = j;
b[k] = 1; // 标记k为白点
if(k!=1) cout<<pre[k]<<" "<<k<<endl;
for(int j=1; j<=n; j++) //修改与k相连的所有蓝点
if(!b[j] && g[k][j] && g[k][j]<minn[j])
{ minn[j] = g[k][j];
pre[j] = k;
}
}
return 0;
}
/*
【输入样例1】
5 8
1 2 2
2 5 9
5 4 7
4 1 10
1 3 12
4 3 6
5 3 3
2 3 8
【输出样例1】
1 2
2 3
3 5
3 4
【输入样例2】 //对应PPT上的图 A~F用1~6表示
6 7
1 2 10
1 3 9
1 6 7
2 4 6
2 6 8
3 4 13
5 6 3
【输出样例2】
1 6
6 5
6 2
2 4
1 3
*/
单源最短路迪杰斯特拉
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
# define next nex
const int maxn=1000001;
int first[maxn],next[maxn<<1],to[maxn<<1],val[maxn<<1],tot;
int n,m;
void add(int x,int y,int z)
{
next[++tot]=first[x];
first[x]=tot;
to[tot]=y;
val[tot]=z;
}
struct node
{
int p;int d;//p点 d权值
bool operator <(const node &a) const
{
return d>a.d;
}
};
int dis[maxn],vis[maxn];
int pre[maxn];
priority_queue<node>q;
void dijkstra(int s,int t)
{
dis[s]=0;
pre[s]=-1;
q.push((node){s,0}) ;
while (!q.empty())
{
node n1=q.top() ;
int k=n1.p ;
q.pop() ;
if(vis[k]) continue;
vis[k]=1;
for(int e=first[k];e;e=next[e])
{
int v=to[e];
if(!vis[v]&&dis[v]>dis[k]+val[e])
{
dis[v]=dis[k]+val[e];
q.push((node){v,dis[v]}) ;
pre[v]=k;//到v最短的路径 是由k更新来的
}
}
}
}
void prt(int t)//输出路径
{
if(pre[t]==-1)
{
cout<<t;
return ;
}
prt(pre[t]);
cout<<"->"<<t;
}
int main()
{
cin>>n>>m;
int s,t;
cin>>s>>t;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
//add(y,x,z);
}
memset(dis,0x7f,sizeof(dis));
dijkstra(s,t);
cout<<dis[t]<<endl;
prt(t);
return 0;
}
/*
5 7
0 3
0 1 13
0 2 38
1 2 15
1 4 14
4 2 6
2 3 19
4 3 17
*/
拓扑排序
#include<iostream>
#include<stack>
#include<vector>
# define next nex
using namespace std;
const int maxn=1e5+3;
vector<int>ans;
int first[maxn],next[maxn<<1],to[maxn<<1];
int tot;
void add(int x,int y)
{
next[++tot]=first[x];
first[x]=tot;
to[tot]=y;
}
int in_num[maxn];
stack<int>sk;
void tuopu(int x)
{
sk.push(x);
while(!sk.empty())
{
int k=sk.top();
ans.push_back(k);
sk.pop();
for(int e=first[k];e;e=next[e])
{
int v=to[e];
in_num[v]--;
if(in_num[v]==0)
{
sk.push(v);
}
}
}
}
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
char X ,Y;
int x,y;
cin>>X>>Y;
x=X-'A';
y=Y-'A';
in_num[y]++;
add(x,y);
}
for(int i=0;i<n;i++)
{
if(in_num[i]==0)
{
tuopu(i);
}
}
for(int i=0;i<n;i++)
{
cout<<char(ans[i]+'A')<<" ";
}
return 0;
}
/*
5 5
A B
A C
B E
C D
E D
ABCED
ABECD
*/