今天在整理电脑的时候发现上个学期学的数据结构还没有整理成博客。今天整理整理。
数据结构实验代码实例
顺序表
代码示例:
#include<bits/stdc++.h>
#define MAXSIZE 1024
using namespace std;
typedef int elemtype;
typedef struct {
elemtype data[MAXSIZE];
int last;
}SequenList;
bool cmp(int a,int b)
{
return (b<a);
}
SequenList* init()
{
SequenList* L;
L=(SequenList*)malloc(sizeof(SequenList));
L->last=-1;
return L;
}
SequenList* creat(SequenList* L)
{
int x;
printf("请输入要存储的数据(以0为结束):");
scanf("%d",&x);
while(1)
{
L->last++;
L->data[L->last]=x;
scanf("%d",&x);
if(x==0)
return L;
}
}
void Print(SequenList* L)
{
int i;
for(i=0;i<=L->last;i++)
printf("%d ",L->data[i]);
printf("\n");
}
void mumen()
{
printf("1.删除\n");
printf("2.插入\n");
printf("3.查找\n");
printf("4.排序\n");
printf("5.销毁\n");
}
int find(SequenList* L,int x)
{
int i,j;
for(i=0;i<=L->last;i++)
if(L->data[i]==x)
return i;
return -1;
}
void delet(SequenList* L,int x)
{
int i,j;
for(i=0;i<=L->last&&L->data[i]!=x;i++);
for(j=i+1;j<=L->last;j++)
L->data[j-1]=L->data[j];
L->last--;
}
void insert(SequenList* L,int index)
{
int data,i;
if(index<1||index>L->last+2)
{
printf("位置错误!\n");
return ;
}
printf("请输入要插入的数据:");
scanf("%d",&data);
for(i=L->last+1;i>index-1;i--)
{
L->data[i]=L->data[i-1];
}
L->data[i]=data;
L->last++;
printf("插入成功!\n");
}
void data_sort(SequenList* L)
{
int x;
printf("1.升序排序\n");
printf("2.降序排序\n");
scanf("%d",&x);
if(x==1)
sort(L->data,L->data+L->last+1);
if(x==2)
sort(L->data,L->data+L->last+1,cmp);
}
void destroy(SequenList* L)
{
free(L);
}
int main()
{
SequenList* L;
L=init();
L=creat(L);
Print(L);
int n,x,f,index,f1=0;
while(1)
{
mumen();
scanf("%d",&n);
switch(n)
{
case 1:
printf("请输入要删除的数据:");
scanf("%d",&x);
f=find(L,x);
if(f==-1)
printf("未找到该数\n");
else
{
delet(L,x);
printf("删除成功!\n");
Print(L);
}
break;
case 2:
printf("请选择要插入的位置:");
scanf("%d",&index);
insert(L,index);
Print(L);
break;
case 3:
printf("请输入要查询的数据:");
scanf("%d",&x);
f=find(L,x);
if(f==-1)
printf("没有该数\n");
else
printf("存在该数,在第%d位\n",f+1);
Print(L);
break;
case 4:
data_sort(L);
Print(L);
break;
case 5:
destroy(L);
printf("顺序表已销毁\n");
f1=1;
}
if(f1==1)
break;
}
}
迷宫问题(栈)
这个题就是个dfs题,但是思想是栈,最后打印路径用到了栈。程序结尾附样例。
#include<bits/stdc++.h>
using namespace std;
struct dis{
int x,y;
};
stack<struct dis> s,s1;
int dd[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int vis[11][11];
int mp[11][11];
int n,m,f=0;
struct dis p;
void Migong(int x,int y)
{
int x1,y1;
struct dis t;
if(x==n-2&&y==m-2)
{
f=1;
while(!s.empty())
{
s1.push(s.top());
s.pop();
}
while(!s1.empty())
{
t=s1.top();
s1.pop();
printf("(%d,%d)\n",t.x,t.y);
}
return ;
}
for(int i=0;i<4;i++)
{
x1=x+dd[i][0];
y1=y+dd[i][1];
if(mp[x1][y1]==0&&vis[x1][y1]==0)
{
vis[x1][y1]=1;
p.x=x1;
p.y=y1;
s.push(p);
Migong(x1,y1);
if(!s.empty())
s.pop();
}
}
}
int main()
{
int i;
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&mp[i][j]);
p.x=1,p.y=1;
vis[1][1]=1;
s.push(p);
Migong(1,1);
if(f==0)
printf("此迷宫不通\n");
}
/*
正常:
1 1 1 1 1 1 1
1 0 0 1 0 0 1
1 0 0 1 0 1 1
1 0 0 0 0 0 1
1 0 1 0 1 0 1
1 0 1 0 1 0 1
1 1 1 1 1 1 1
有岔路:
1 1 1 1 1 1 1
1 0 0 1 0 0 1
1 0 0 1 0 1 1
1 0 0 0 0 1 1
1 0 1 0 1 0 1
1 0 1 0 0 0 1
1 1 1 1 1 1 1
不通:
1 1 1 1 1 1 1
1 0 0 1 0 0 1
1 0 0 1 0 1 1
1 0 0 0 0 1 1
1 0 1 0 1 0 1
1 0 1 0 1 0 1
1 1 1 1 1 1 1
*/
表达式求值(栈)
实验要求链栈,但是感觉并没有必要,就用了数组代替。此程序分为两部分,中缀转后缀和表达式求值。注意表达式的运算规则,负数,小数的运算
#include <bits/stdc++.h>
using namespace std;
stack<char> st;
stack<double> val;
int Judge(char c)
{
if (c == '+' || c == '-')
return 1;
else if (c == '*' || c == '/')
return 2;
else if (c == '(')
return 3;
else if (c == ')')
return 4;
return 0;
}
void cul()
{
char c;
c=st.top();
double a,b;
if (c == '+')
{
a = val.top();
val.pop();
b = val.top();
val.pop();
val.push(b + a);
}
else if (c == '-')
{
a = val.top();
val.pop();
b = val.top();
val.pop();
val.push(b - a);
}
else if (c == '*')
{
a = val.top();
val.pop();
b = val.top();
val.pop();
val.push(b * a);
}
else if (c == '/')
{
a = val.top();
val.pop();
b = val.top();
val.pop();
val.push(b / a);
}
}
int ff=0;
int main()
{
int f1 = 1,n;
double sum = 0, sum1 = 0, cheng = 0.1;
int i = 0, f;
char s[100];
printf("请输入:\n");
printf("1.中缀转后缀\n");
printf("2.表达式求值\n");
scanf("%d",&n);
if(n==1)
{
printf("请输入表达式:");
scanf("%s", s);
while (s[i] != '\0')
{
f = Judge(s[i]);
if (f != 0)
{
switch (f)
{
case 1:
if (s[i] == '+' && (i == 0 || (s[i - 1] <= '0' || s[i - 1] >= '9')) && s[i - 1] != ')')
{
i++;
continue;
}
else if (s[i] == '-' && (i == 0 || (s[i - 1] <= '0' || s[i - 1] >= '9')))
{
ff=1;
i++;
continue;
}
else if (s[i] == '-' || s[i] == '+')
{
while (1)
{
if (st.empty() || st.top() == '(')
{
st.push(s[i]);
break;
}
else if (st.top() == '+' || st.top() == '-' || st.top() == '*' || st.top() == '/')
{
if (f1 == 1)
{
f1 = 0;
printf("%c", st.top());
}
else
printf(" %c", st.top());
st.pop();
}
else
break;
}
}
break;
case 2:
while (1)
{
if (st.empty() || st.top() == '+' || st.top() == '-' || st.top() == '(')
{
st.push(s[i]);
break;
}
else if (st.top() == '*' || st.top() == '/')
{
if (f1 == 1)
{
f1 = 0;
printf("%c", st.top());
}
else
printf(" %c", st.top());
st.pop();
}
else
break;
}
break;
case 3:
st.push(s[i]);
break;
case 4:
while (1)
{
if (st.top() == '(')
{
st.pop();
break;
}
else
{
if (f1 == 1)
{
f1 = 0;
printf("%c", st.top());
}
else
printf(" %c", st.top());
st.pop();
}
}
break;
}
}
else
{
while (s[i] >= '0' && s[i] <= '9')
{
sum = sum * 10 + s[i] - '0';
i++;
}
if (s[i] == '.')
{
sum1 = 0;
i++;
while (s[i] >= '0' && s[i] <= '9')
{
sum1 = sum1 + (s[i] - '0') * cheng;
cheng = cheng * 0.1;
i++;
}
}
i--;
if (sum1 != 0)
{
if (f1 == 1)
{
f1 = 0;
cout << sum + sum1;
}
else
cout <<" "<< sum + sum1 ;
}
else if (f1 == 1)
{
f1 = 0;
printf("%.f", sum);
}
else
printf(" %.f", sum);
cheng = 0.1;
sum1 = 0;
sum = 0;
}
i++;
}
while (!st.empty())
{
if (f1 == 1)
{
f1 = 0;
printf("%c", st.top());
}
else
printf(" %c", st.top());
st.pop();
}
}
else
{
string s1;
char s2[100];
int a,b;
printf("请输入表达式:");
scanf("%s", s);
while (s[i] != '\0')
{
f = Judge(s[i]);
if (f != 0)
{
switch (f)
{
case 1:
if (s[i] == '+' && (i == 0 || (s[i - 1] <= '0' || s[i - 1] >= '9')) && s[i - 1] != ')')
{
i++;
continue;
}
else if (s[i] == '-' && (i == 0 || (s[i - 1] <= '0' || s[i - 1] >= '9')))
{
ff=1;
i++;
continue;
}
else if (s[i] == '-' || s[i] == '+')
{
while (1)
{
if (st.empty() || st.top() == '(')
{
st.push(s[i]);
break;
}
else if (st.top() == '+' || st.top() == '-' || st.top() == '*' || st.top() == '/')
{
cul();
st.pop();
}
else
break;
}
}
break;
case 2:
while (1)
{
if (st.empty() || st.top() == '+' || st.top() == '-' || st.top() == '(')
{
st.push(s[i]);
break;
}
else if (st.top() == '*' || st.top() == '/')
{
cul();
st.pop();
}
else
break;
}
break;
case 3:
st.push(s[i]);
break;
case 4:
while (1)
{
if (st.top() == '(')
{
st.pop();
break;
}
else
{
cul();
st.pop();
}
}
break;
}
}
else
{
while (s[i] >= '0' && s[i] <= '9')
{
sum = sum * 10 + s[i] - '0';
i++;
}
if (s[i] == '.')
{
sum1 = 0;
i++;
while (s[i] >= '0' && s[i] <= '9')
{
sum1 = sum1 + (s[i] - '0') * cheng;
cheng = cheng * 0.1;
i++;
}
}
i--;
if(ff==1)
val.push(-(sum+sum1));
else
val.push(sum+sum1);
ff=0;
cheng = 0.1;
sum1 = 0;
sum = 0;
}
i++;
}
while (!st.empty())
{
cul();
st.pop();
}
double ta=0,tb=0;
ta=val.top();
val.pop();
if(!val.empty())
{
tb=val.top();
}
printf("%lf\n",ta+tb);
}
}
/*
2+3*(7-4)+8/4
*/
表达式树的构建
这个属于实验外的东西了,老师布置的课余时间的作业,做着玩玩。
老师要求的是自动出题器,用树来表示,主要思想就是叶子节点是运算数,非叶子节点是运算符,这样通过中序遍历就可以得到一个表达式,c语言很难把整棵树形象的表示出来,我用了括号来表示。
#include<bits/stdc++.h>
using namespace std;
typedef struct t
{
int data;
struct t *l,*r;
int h;
} Tree;
Tree* create(int h)
{
Tree* t;
int num;
int c;
if(h==5)
return NULL;
else
{
t= (Tree*)malloc(sizeof(Tree));
if(h==0)
{
int magic=rand()%4;
if(magic==3) c=-3;
else if(magic==2) c=-2;
else if(magic==1) c=-1;
else if(magic==0) c=-4;
t->data=c;
}
else if(h==4)
{
int magic=rand()%100;
t->data=magic;
}
else
{
int magic=rand()%5;
if(magic>3)
{
magic=rand()%10;
printf("%d\n",magic);
t->data=magic;
return t;
}
if(magic==3) c=-3;
else if(magic==2) c=-2;
else if(magic==1) c=-1;
else if(magic==0) c=-4;
t->data=c;
}
t->l=create(h+1);
t->r=create(h+1);
}
return t;
}
void Print(Tree* T)
{
if(T)
{
if(T->data>=0)
printf("%d",T->data);
else
{
printf("(");
Print(T->l);
if(T->data==-4) printf("+");
if(T->data==-1) printf("-");
if(T->data==-2) printf("*");
if(T->data==-3) printf("/");
Print(T->r);
printf(")");
}
}
}
int main()
{
srand((unsigned) time(NULL));
Tree* T;
T=create(0);
Print(T);
}
杨辉三角(队列)
杨辉三角的生成一般是用不着队列的,也许用队列实现就只是单纯的练习一下队列的操作吧,我这次没有用STL的队列,毕竟了解一下底层实现也挺好的。。。
如果想用别的方法生成杨辉三角,请移步我的另一篇博客 杨辉三角形
#include<stdio.h>
#include<memory.h>
#include<stdlib.h>
#define MAXSIZE 100
typedef struct queue
{
int data[100];
int rear,front;
}Queue;
Queue* init()
{
Queue* q;
q=(Queue*)malloc(sizeof(Queue));
memset(q->data,0,sizeof(q->data));
q->front=q->rear=0;
return q;
}
void enqueue(Queue *q,int x)
{
q->data[q->rear]=x;
q->rear=(q->rear+1)%MAXSIZE;
}
int dequeue(Queue* q)
{
int x;
x=q->data[q->front];
q->front=(q->front+1)%MAXSIZE;
return x;
}
int getqueue(Queue* q)
{
return q->data[q->front];
}
int isempty(Queue* q)
{
if(q->front==q->rear)
return 1;
return 0;
}
void PrintTriangle(Queue* q,int n)
{
int x,t;
enqueue(q,1);
for(int i=2;i<=n;i++)
{
enqueue(q,1);
for(int j=1;j<=i-2;j++)
{
t=dequeue(q);
printf("%d ",t);
x=getqueue(q);
t=t+x;
enqueue(q,t);
}
x=dequeue(q);
printf("%d ",x);
enqueue(q,1);
printf("\n");
}
while(!isempty(q))
{
x=dequeue(q);
printf("%d ",x);
}
}
int main()
{
int n;
Queue* q;
q=init();
scanf("%d",&n);
PrintTriangle(q,n);
}
二叉树
二叉树的递归遍历
递归遍历没什么好说的
#include <stdio.h>
#include <stdlib.h>
typedef struct tree
{
int data;
struct tree *r, *l;
} Tree;
int a[100];
Tree *create()
{
int x;
Tree *T;
scanf("%d", &x);
if (x == 0)
return NULL;
else
{
T = (Tree *)malloc(sizeof(Tree));
T->data = x;
T->l = create();
T->r = create();
}
return T;
}
void Printpre(Tree *T)
{
if (T)
{
printf("%d ", T->data);
Printpre(T->l);
Printpre(T->r);
}
return;
}
void Printmid(Tree *T)
{
if (T)
{
Printmid(T->l);
printf("%d ", T->data);
Printmid(T->r);
}
return;
}
void Printaft(Tree *T)
{
if (T)
{
Printaft(T->l);
Printaft(T->r);
printf("%d ", T->data);
}
return;
}
int main()
{
Tree *T;
printf("请先序输入树节点的值,如没有,则用0代替:");
T = create();
printf("先序遍历结果:");
Printpre(T);
printf("\n");
printf("中序遍历结果:");
Printmid(T);
printf("\n");
printf("后序遍历结果:");
Printaft(T);
}
/*
1 2 4 0 0 5 0 0 3 0 0
1 2 4 6 0 0 0 5 7 0 0 0 3 0 8 0 0
*/
二叉树非递归遍历
主要是练习栈的使用,还有队列的层序遍历
#include<bits/stdc++.h>
using namespace std;
typedef struct tree
{
int data;
bool flag;
struct tree *r, *l;
} Tree;
queue<Tree*> q;
int a[100];
Tree *create()
{
int x;
Tree *T;
scanf("%d", &x);
if (x == 0)
return NULL;
else
{
T = (Tree *)malloc(sizeof(Tree));
T->data = x;
T->l = create();
T->r = create();
}
return T;
}
void InorderTraversal( Tree* BT )
{
stack<Tree*> S;
Tree* T;
T=BT;
while(T||!S.empty())
{
while(T)
{
S.push(T);
T=T->l;
}
if(!S.empty())
{
T=S.top();
S.pop();
printf(" %d",T->data);
T=T->r;
}
}
}
void PreorderTraversal( Tree* BT )
{
stack<Tree*> S;
Tree* T;
T=BT;
while(T||!S.empty())
{
while(T)
{
printf(" %d",T->data);
S.push(T);
T=T->l;
}
if(!S.empty())
{
T=S.top();
S.pop();
T=T->r;
}
}
}
void PostorderTraversal( Tree* BT )
{
stack<Tree*> S;
Tree* T=BT;
Tree* p;
while(T||!S.empty())
{
while(T)
{
T->flag=true;
S.push(T);
T=T->l;
}
while(!S.empty())
{
p=S.top();
if(p->flag==true)
break;
T=S.top();
S.pop();
printf(" %d",T->data);
T=NULL;
}
if(!S.empty())
{
p=S.top();
p->flag=false;
T=p->r;
}
}
}
void cengPrint(Tree* T)
{
Tree* T1;
q.push(T);
while(!q.empty())
{
T1=q.front();
q.pop();
printf("%d ",T1->data);
if(T1->l!=NULL)
q.push(T1->l);
if(T1->r!=NULL)
q.push(T1->r);
}
}
int main()
{
Tree *T;
printf("请先序输入树节点的值,如没有,则用0代替:");
T = create();
printf("先序遍历结果:");
PreorderTraversal(T);
printf("\n");
printf("中序遍历结果:");
InorderTraversal(T);
printf("\n");
printf("后序遍历结果:");
PostorderTraversal(T);
printf("\n");
printf("层序遍历结果:");
cengPrint(T);
}
/*
1 2 4 0 0 5 0 0 3 0 0
1 2 4 6 0 0 0 5 7 0 0 0 3 0 8 0 0
*/
哈夫曼树
开始是直接写的,没有对文件的操作,但是后来想了想,既然写了,那就带上文件操作吧,这样看起来更完整些
#include<bits/stdc++.h>
#include<windows.h>
#define inf 999999
using namespace std;
char s[10000];
map<char,double> mp;
map<char,string> mp1;
int n;
int m;
struct node
{
int w;
char data;
char *ma;
int par,l,r;
};
string ll;
string s1;
struct node Tree[1000];
struct node * p;
bool cmp(struct node a,struct node b)
{
return a.w<b.w;
}
void GetFZ()
{
int i;
gets(s);
int len=strlen(s);
for(i=0; i<len; i++)
mp[s[i]]++;
map<char,double> ::iterator it;
for(it=mp.begin(); it!=mp.end(); it++)
n++;
m=2*n-1;
for(p=Tree,i=0,it=mp.begin(); it!=mp.end()&&i<n; it++,p++)
{
p->w=it->second;
p->data=it->first;
p->par=-1;
p->l=-1;
p->r=-1;
}
for(; i<m; i++,p++)
{
p->w=0;
p->l=-1;
p->r=-1;
p->par=-1;
p->data=' ';
}
int m1,m2,x1,x2,j;
for(i=n; i<m; i++)
{
m1=m2=inf;
x1=x2=0;
for(j=0; j<i; j++)
{
if(Tree[j].par==-1&&Tree[j].w<m1)
m2=m1,x2=x1,m1=Tree[j].w,x1=j;
else if(Tree[j].par==-1&&Tree[j].w<m2)
m2=Tree[j].w,x2=j;
}
Tree[x1].par=i;
Tree[x2].par=i;
Tree[i].l=x1;
Tree[i].r=x2;
Tree[i].w=m1+m2;
}
}
void GetFZ(int x)
{
int i;
ifstream in("yuanwenjian.txt");
if(in) // 有该文件
getline (in, ll);// line中不包括每行的换行符
int len=ll.size();
for(i=0; i<len; i++)
mp[ll[i]]++;
map<char,double> ::iterator it;
for(it=mp.begin(); it!=mp.end(); it++)
n++;
m=2*n-1;
for(p=Tree,i=0,it=mp.begin(); it!=mp.end()&&i<n; it++,p++)
{
p->w=it->second;
p->data=it->first;
p->par=-1;
p->l=-1;
p->r=-1;
}
for(; i<m; i++,p++)
{
p->w=0;
p->l=-1;
p->r=-1;
p->par=-1;
p->data=' ';
}
int m1,m2,x1,x2,j;
for(i=n; i<m; i++)
{
m1=m2=inf;
x1=x2=0;
for(j=0; j<i; j++)
{
if(Tree[j].par==-1&&Tree[j].w<m1)
m2=m1,x2=x1,m1=Tree[j].w,x1=j;
else if(Tree[j].par==-1&&Tree[j].w<m2)
m2=Tree[j].w,x2=j;
}
Tree[x1].par=i;
Tree[x2].par=i;
Tree[i].l=x1;
Tree[i].r=x2;
Tree[i].w=m1+m2;
}
}
void JetTree()
{
int i,c,f,str;
struct node Jie[n+1];
char s1[n+1];
s1[n-1]='\0';
for(i=0; i<n; i++)
{
str=n-1;
for(c=i,f=Tree[i].par; f!=-1; c=f,f=Tree[f].par)
if(Tree[f].l==c) s1[--str]='0';
else s1[--str]='1';
Tree[i].ma=(char*)malloc((n-str)*sizeof(char));
strcpy(Tree[i].ma,&s1[str]);
mp1[Tree[i].data]=Tree[i].ma;
}
}
void Jiema()
{
int i;
for(i=0;i<m;i++)
if(Tree[i].par==-1)
break;
int pos=i;
int pos1=pos;
int k=0;
while(1)
{
if(Tree[pos1].l==-1&&Tree[pos1].r==-1)
{
printf("%c",Tree[pos1].data);
s1+=Tree[pos1].data;
pos1=pos;
continue;
}
else if(ll[k]=='0')
pos1=Tree[pos1].l;
else if(ll[k]=='1')
pos1=Tree[pos1].r;
else
break;
k++;
}
printf("\n");
}
int main()
{
int ff;
string ss;
printf("1. 从文件解码\n2. 压缩到文件\n3. 从文件读入并压缩\n");
ofstream fout;
while(1)
{
scanf("%d",&ff);getchar();
if(ff==1)
{
ifstream in("yasuo.txt");
if(in) // 有该文件
getline (in, ll);// line中不包括每行的换行符
// GetFZ(1);
Jiema();
}
else if(ff==2)
{
GetFZ();
JetTree();
for(int i=0; i<strlen(s); i++)
{
ss+=mp1[s[i]];
}
fout.open("yasuo.txt");
cout<<ss<<endl;
fout<<ss<<endl;
fout.close();
for(int i=0; i<n; i++)
printf("%c %s\n",Tree[i].data,Tree[i].ma);
printf("压缩成功!\n");
}
else if(ff==3)
{
GetFZ(1);
JetTree();
for(int i=0; i<ll.size(); i++)
ss+=mp1[ll[i]];
for(int i=0; i<n; i++)
printf("%c %s\n",Tree[i].data,Tree[i].ma);
fout.open("yasuo.txt");
cout<<ss<<endl;
fout<<ss<<endl;
fout.close();
}
}
}
图论
图的深度优先遍历
图论最基础就是遍历,深度优先遍历,简称dfs
这个程序是最最简单的dfs板子。
#include<stdio.h>
int mp[100][100];//存储图
int vis[100];//判断是否便利过,遍历过置成1
int num,bian;
void dfs(int x)
{
int i;
vis[x]=1;//遍历这个顶点,置1
printf("%d ",x);//输出这个节点。
for(i=0;i<num;i++)//站在这个点上,看其他所有点
if(vis[i]==0&&mp[x][i]==1)//如果这个点没有遍历过(vis[i]==0),并且 x 顶点和 i 顶点有边 ,递归进去。
dfs(i);
return ;
}
int main()
{
int i,x,y;
scanf("%d%d",&num,&bian);//输入顶点个数,边的个数。
for(i=0;i<bian;i++)
{
scanf("%d%d",&x,&y);//输入一个边的两个顶点,比如输入3 4,说明顶点3和顶点4之间有边
mp[x][y]=mp[y][x]=1;//mp[3][4]=1,就说明3和4之间有边
}
dfs(0);//从顶点0开始遍历。
}
/*
8 10
0 1
0 2
1 3
1 4
2 5
2 6
3 7
4 7
5 7
6 7
*/
图的广度优先遍历
广度优先遍历简称bfs
#include<stdio.h>
int mp[100][100];
int vis[100];
int num,bian;
void bfs(int x)
{
int q[1000],rear=0,front=0;//模拟一个队列
int i;
vis[x]=1;//访问过,置 1
q[rear++]=x;//元素入队列
while(rear!=front)//当队列中有元素的时候,一直循环。
{
int p=q[front++];//取队头元素
printf("%d ",p);
for(i=0;i<num;i++)//站在这个顶点上看
{
if(vis[i]==0&&mp[p][i]==1)//如果顶点 i 没有访问过,并且 p顶点和 i 顶点有边。则 置 1 ,并 入队
{
vis[i]=1;
q[rear++]=i;
}
}
}
}
int main()
{
int i,x,y;
scanf("%d%d",&num,&bian);
for(i=0;i<bian;i++)
{
scanf("%d%d",&x,&y);;
mp[x][y]=mp[y][x]=1;
}
bfs(0);
}
Prim最小生成树算法
这个也是很基础的最小生成树算法了
#include<bits/stdc++.h>
#define inf 99999
using namespace std;
int mp[100][100];
int dis[100];
int vis[100];
int num;
void prim(int x)
{
int sum=0,i,j;
vis[x]=1;
for(i=0;i<num;i++)
dis[i]=mp[x][i];
int u=-1;
for(i=1;i<num;i++)
{
int min=inf;
for(j=0;j<num;j++)
{
if(vis[j]==0&&dis[j]<min)
min=dis[u=j];
}
if(u==-1)
break;
sum+=min;
vis[u]=1;
for(j=0;j<num;j++)
if(vis[j]==0&&dis[j]>mp[u][j])
dis[j]=mp[u][j];
}
printf("sum = %d",sum);
}
int main()
{
int bian,i,j,x,y,w;
scanf("%d%d",&num,&bian);
for(i=0;i<bian;i++)
for(j=0;j<bian;j++)
mp[i][j]=inf;
for(i=0;i<bian;i++)
{
scanf("%d%d%d",&x,&y,&w);
mp[x][y]=w;
mp[y][x]=w;
}
prim(0);
}
/*
7 12
0 1 2
0 2 4
0 3 1
1 3 3
1 4 10
2 3 2
2 5 5
3 5 8
3 6 4
3 4 7
5 6 1
4 6 6
*/
Kruskal最小生成树算法
老师上课讲的是将各边的关系存在一个链表里,维护这个链表,但这种方法太麻烦了。
用并查集就行。
#include<bits/stdc++.h>
using namespace std;
struct Gr{
int u,v,w;
}G[1000];
int a[1000];
int num;
int bian;
bool cmp(struct Gr a,struct Gr b)
{
return a.w<b.w;
}
void init()
{
for(int i=0;i<=num;i++)
a[i]=i;
}
int find(int x)
{
return a[x]==x?x:a[x]=find(a[x]);
}
void unio(int x,int y)
{
int xx=find(x);
int yy=find(y);
if(xx!=yy)
a[xx]=yy;
}
void Kruskal()
{
int sumw=0;
int num1=0;
int u,v,i;
init();
for(i=0;i<bian;i++)
{
u=G[i].u;
v=G[i].v;
if(find(u)!=find(v))
{
printf( "( %d , %d ) w = %d\n", u, v, G[i].w );
unio(u,v);
sumw+=G[i].w;
num1++;
}
if(num1==num)
break;
}
printf("\n\tsum = %d",sumw);
}
int main()
{
int i,u,v,w;
scanf("%d%d",&num,&bian);
for(i=0;i<bian;i++)
{
scanf("%d%d%d",&u,&v,&w);
G[i].u=u;
G[i].v=v;
G[i].w=w;
}
sort(G,G+bian,cmp);
Kruskal();
printf("\n");
}
/*
7 12
0 1 2
0 2 4
0 3 1
1 3 3
1 4 10
2 3 2
2 5 5
3 5 8
3 6 4
3 4 7
5 6 1
4 6 6
*/
Dijkstra最短路径算法
最经典的求最短路径算法
#include<bits/stdc++.h>
#define inf 99999
using namespace std;
int mp[100][100];
int dis[100];
int vis[100];
int num;
void Dijkstra(int x)
{
int i,j;
vis[x]=1;
for(i=0; i<num; i++)
dis[i]=mp[x][i];
int u;
for(i=1; i<num; i++)
{
int min=inf;
u=x;
for(j=0; j<num; j++)
{
if(vis[j]==0&&min>dis[j])
min=dis[u=j];
}
vis[u]=1;
for(j=0; j<num; j++)
{
if(vis[j]==0&&min+mp[u][j]<dis[j])
dis[j]=mp[u][j]+min;
}
}
}
void init()
{
int i,j;
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
}
int main()
{
int bian,i,j,x,y,w;
scanf("%d%d",&num,&bian);
for(i=0; i<bian; i++)
for(j=0; j<bian; j++)
mp[i][j]=inf;
for(i=0; i<bian; i++)
{
scanf("%d%d%d",&x,&y,&w);
mp[x][y]=w;
}
for(i=0; i<num; i++)
{
init();
Dijkstra(i);
for(j=0; j<num; j++)
{
if(j!=i)
printf("v(%d) ---> (%d) = %d\n",i,j,dis[j]);
}
printf("\n");
}
}
/*
5 9
0 1 3
0 4 30
1 2 25
1 3 8
2 4 10
3 2 4
3 0 20
3 4 12
4 0 5
*/
关键路径
关键路径可以说是很实用的算法了,在各个工程中使用最多
写起来也比较繁琐
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
struct node{
int u,v,w;
}e[100];
int n,m,into[100],Stack[100], mp[100][100];
int inf=999999,min;
int ve[100],vl[100],ee[100],el[100];
void topo()//拓扑求最大路径
{
int cnt = 0;//栈顶指针为零
for(int i = 1; i <= n; i++) //数次寻找
{
int k=-1;
for(int j=1; j<= n; j++)
{
if(into[j]==0)//如果入度为0,可以进栈了
{
Stack[++cnt] = j;
k = j;
into[j] = -1;
break;//如果有为零的就可以立刻结束
}
}
for(int j = 1; j <= n; j++)
if(mp[k][j] != inf)//假如联通
{
ve[j] = max(ve[j], ve[k] + mp[k][j]);//找到最大路径
into[j]--;//入度减一
}
}
}
void solve()
{
topo();
memset(vl, inf, sizeof(vl));//最晚发生时间初始为最大
vl[Stack[n]] = ve[Stack[n]];//最晚等于最大路径
for(int i = n; i >= 1; i--) //从后向前找
for(int j = 1; j <= n; j++)
if(mp[Stack[i]][j] != inf) //如果两点之间有联系
vl[Stack[i]] = (vl[j] - mp[Stack[i]][j])< vl[Stack[i]]?(vl[j] - mp[Stack[i]][j]):vl[Stack[i]];//更新最晚时
for(int i = 1; i <= m; i++) //计算ee
ee[i] = ve[e[i].u];
for(int i = 1; i <= m; i++)//计算el
el[i] = vl[e[i].v] - e[i].w;
printf("\n");
for(int i = 1; i <= m; i++)
if(ee[i] == el[i])
printf("%d %d %d\n", e[i].u, e[i].v, e[i].w);//输出关键路径
}
int main()
{
scanf("%d%d", &n, &m);
for(int i=0;i<=100;i++)
for(int j=0;j<=100;j++)
mp[i][j]=inf; //将未联通的点初始为最大值
for(int i = 1; i <= m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
e[i].u = u;
e[i].v = v;
e[i].w = w;
mp[u][v] = w;
into[v]++;//入度增加
}
solve();
return 0;
}
图论小综合(校园导航系统)
学习完图论,做了一个小系统玩,校园导航
用到了最短路径和路径打印,还有一个弗洛伊德算法,没有用到。
#include <stdio.h>
#include<windows.h>
#include <string.h>
#include<memory.h>
#define MaxSightNum 100
#define inf 9999999
typedef struct//SightType
{
int num;
char name[100];
char feature[200];
}SightType;
typedef struct //MGragh
{
SightType sights[MaxSightNum];
int edges[MaxSightNum][MaxSightNum];
int n,e;
}MGraph;
MGraph hbu;
int stack[1000];
int top=-1;
int Dis[MaxSightNum];
int vis[MaxSightNum];//是否访问过
int path[MaxSightNum];//前驱景点
char name[][12]={"校医院","操场","校门西口","古楼实验室","校门南门","图书馆","大食堂","信息院楼","综合楼","男生宿舍",
"女生宿舍","超市"};
char feature[][100]={"这里是学校医务室","运动的地方","西门有小吃","我们上实验的地方","学校大门口","看书的地方","吃饭的地方,饭很好吃",
"信息院老师办公的地方","很高","男生宿舍","女生宿舍","买一些生活用品"};
void Mmenu()//主菜单
{
printf(" 欢迎使用河北农业大学校园导航系统 \n\n\n");
printf(" 1.管理者模式\n");
printf(" 2.游客模式\n");
printf(" 3.退出\n");
printf(" 请输入您想进入的模式: ");
}
void map()//地图
{
}
void creat()//创建地图
{
int i,j;
hbu.e=20;
hbu.n=12;
for(i=0;i<hbu.n;i++)
{
hbu.sights[i].num=i;
strcpy(hbu.sights[i].name,name[i]);
strcpy(hbu.sights[i].feature,feature[i]);
}
for(i=0;i<hbu.e;i++)
{
for(j=0;j<hbu.e;j++)
{
hbu.edges[i][j]=inf;
}
}
hbu.edges[0][1]=hbu.edges[1][0]=350;
hbu.edges[0][4]=hbu.edges[4][0]=200;
hbu.edges[1][2]=hbu.edges[2][1]=200;
hbu.edges[1][4]=hbu.edges[4][1]=480;
hbu.edges[1][5]=hbu.edges[5][1]=280;
hbu.edges[2][3]=hbu.edges[3][2]=100;
hbu.edges[2][6]=hbu.edges[6][2]=100;
hbu.edges[3][6]=hbu.edges[6][3]=100;
hbu.edges[4][5]=hbu.edges[5][4]=400;
hbu.edges[4][7]=hbu.edges[7][4]=500;
hbu.edges[4][8]=hbu.edges[8][4]=500;
hbu.edges[5][9]=hbu.edges[9][5]=50;
hbu.edges[5][10]=hbu.edges[10][5]=300;
hbu.edges[6][10]=hbu.edges[10][6]=100;
hbu.edges[7][11]=hbu.edges[11][7]=400;
hbu.edges[8][11]=hbu.edges[11][8]=400;
hbu.edges[8][9]=hbu.edges[9][8]=100;
hbu.edges[9][11]=hbu.edges[11][9]=500;
hbu.edges[9][10]=hbu.edges[10][9]=200;
hbu.edges[10][11]=hbu.edges[11][10]=600;
}
void amenu()//管理者菜单
{
printf("\n\n\n\n 1.浏览景点信息。\n");
printf(" 2.某一景点到其他景点的最短信息。\n");
printf(" 3.任意两景点的最短路径。\n");
printf(" 4.修改景点信息。\n");
printf(" 5.增加景点。\n");
printf(" 6.删除景点\n");
printf(" 7.增加道路。\n");
printf(" 8.删除道路。\n");
printf(" 9.返回。\n");
printf(" 请输入您的操作选项: ");
}
void tmenu()//游客菜单
{
printf("\n\n\n\n 1.浏览景点信息。\n");
printf(" 2.某一景点到其他景点的最短信息。\n");
printf(" 3.任意两景点的最短路径。\n");
printf(" 4.返回。\n");
printf(" 请输入您的操作选项: ");
}
void print(SightType a)//景点信息输出
{
printf("\n 景点名字:%s",a.name);
printf("\n 景点编号:%d",a.num);
printf("\n 景点介绍:%s\n",a.feature);
system("pause");
system("cls");
}
int searchSight(char sname[])//返回景点编号
{
int i;
for(i=0;i<hbu.n;i++)
{
if(strcmp(hbu.sights[i].name,sname)==0)
{
return i;
}
}
return -1;
}
void GetSightInfo()//景点信息查询
{
char sname[20];//景点名称;
int i;
map();
system("cls");
printf("请输入你要查询信息的景点的名称: ");
scanf("%s",&sname);
i=searchSight(sname);
if(i==-1)
{
printf("\n 没有找到!\n\n\n");
}
else
{
print(hbu.sights[i]);
}
system("pause");
system("cls");
}
void dijkstra(int s)//dijkstra算法
{
//printf("%d\n",s);
int i=0,j,k;
memset(vis,0,sizeof(vis));//数组清零
vis[s]=1;
for(i=0;i<hbu.n;i++)
{
Dis[i]=hbu.edges[s][i];
path[i]=s;
}
path[s]=-1;
for(i=1;i<hbu.n;i++)
{
int min=inf+1;
for(j=0;j<hbu.n;j++)
{
if(vis[j]==0&&min>Dis[j])
{
min=Dis[j];
k=j;
}
}
vis[k]=1;
for(j=0;j<hbu.n;j++)
{
if(vis[j]==0&&min+hbu.edges[k][j]<Dis[j])
{
Dis[j]=min+hbu.edges[k][j];
path[j]=k;
}
}
}
}
void printShortest(int s) //输出一个景点到其他景点的最短路径
{
int i;
for(i=0;i<hbu.n;i++)
{
if(i!=s)
{
if(Dis[i]!=inf)
{
printf("\n%s->%s : %d :",name[s],name[i],Dis[i]);
int pre;
pre=path[i];
while(pre>=0)
{
stack[++top]=pre;
pre=path[pre];
// printf("%d\n",pre);
}
while(top>0)
{
printf("%s->",name[stack[top--]]);
}
printf("%s",name[i]);
}
else
{
printf("\n%s->%s :\t无通路!",name[s],name[i]);
}
}
}
}
void ShortestPath()//一个景点到其他景点的最短路径
{
int s;//查询景点的编号
int i=0;
char name[20];查询景点的名称
system("cls");
printf("请输入要查询的景点名字: ");
scanf("%s",&name);
for(i=0;i<hbu.n;i++)
{
if(strcmp(hbu.sights[i].name,name)==0)
{
s=hbu.sights[i].num;
break;
}
}
if(i==hbu.n)
{
printf("输入不合法!\n");
return ;
}
dijkstra(s);
printShortest(s);
printf("\n\n\n");
system("pause");
system("cls");
}
void changeSightInfo()//修改景点信息
{
char sname[20];//景点名称;
char feature[100];
int i;
map();
system("cls");
printf("请输入你要修改信息的景点名称: ");
scanf("%s",&sname);
i=searchSight(sname);
if(i!=-1)
{
printf("请输入你要修改的描述信息: ");
scanf("%s",&feature);
strcpy(hbu.sights[i].feature,feature);
print(hbu.sights[i]);
printf("\n\n\n\n\t\t\t\t修改成功!!");
system("pause");
system("cls");
}
else
{
printf("\n\n\n\n\t\t\t\t!!");
}
}
void TwoShortest()//求两个景点之间的最短路径
{
int j,k;
char start[20];
char end[20];
int pre;
system("cls");
printf("请输入起始景点: ");
while(1)
{
scanf("%s",&start);
k=searchSight(start);
if(k!=-1)
break;
else
printf("没有找到该景点,请重新输入!\n");
}
printf("请输入终止景点: ");
while(1)
{
scanf("%s",&end);
j=searchSight(end);
if(j!=-1)
break;
else
printf("没有找到该景点,请重新输入!\n");
}
dijkstra(k);
if(Dis[j]!=inf)
{
printf("\n%s->%s : %d :",start,end,Dis[j]);
pre=path[j];
while(pre>=0)
{
stack[++top]=pre;
pre=path[pre];
}
while(top>0)
printf("%s->",name[stack[top--]]);
printf("%s",name[j]);
}
else
printf("\n\n\n\t\t\t没有通路!\n\n");
printf("\n\n\n");
system("pause");
system("cls");
}
void addSight()//添加一个景点
{
int i,w,t, distance;
char end[20];
system("cls");
printf("请输入你要增加的景点名称: ");
scanf("%s",&hbu.sights[hbu.n++].name);
strcpy(name[hbu.n-1],hbu.sights[hbu.n-1].name);
hbu.sights[hbu.n-1].num=hbu.n-1;
printf("请输入该景点的描述信息: ");
scanf("%s",&hbu.sights[hbu.n-1].feature);
printf("请输入该景点与其他景点间的路径数:");
scanf("%d",&w);
for(i=0;i<w;i++)
{
printf("请输入第%d条路径的另一个景点名称: ",i+1);
scanf("%s",&end);
t=searchSight(end);
printf("请输入两景点之间的距离: ");
scanf("%d",&distance);
hbu.edges[t][hbu.n-1]=hbu.edges[hbu.n-1][t]=distance;
hbu.e++;
}
print(hbu.sights[hbu.n-1]);
printf("增加成功!!!\n\n\n");
system("pause");
system("cls");
}
void deleteSight()//删除一个景点
{
int i,d;
char del[20];
system("cls");
printf("请输入你要删除的景点名称: ");
scanf("%s",&del);
d=searchSight(del);
strcpy(hbu.sights[d].feature,"已删除");
for(i=0;i<hbu.n;i++)
{
hbu.edges[i][d]=inf;
hbu.edges[d][i]=inf;
}
printf("\n\n\n\t\t\t\t已删除!\n\n\n");
system("pause");
// system("pause");
system("cls");
}
void addEdges()//增加道路
{
system("cls");
int v,s,e,i,adde;
char start[20],end[20];
printf("请输入你要增加的道路数: ");
scanf("%d",&adde);
for(i=0;i<adde;i++)
{
printf("请输入所添加道路的起点: ");
scanf("%s",start);
printf("请输入所添加道路的终点: ");
scanf("%s",end);
printf("请输入两个景点之间的距离: ");
scanf("%d",&v);
s=searchSight(start);
e=searchSight(end);
hbu.edges[s][e]=hbu.edges[e][s]=v;
}
printf("\n\n\n\t\t\t添加成功!!\n\n");
system("pause");
system("cls");
}
void deleteEdges()//删除道路
{
system("cls");
char start[20],end[20];
int i,dele;
printf("请输入你要删除的道路数: ");
scanf("%d",&dele);
for(i=0;i<dele;i++)
{
printf("请输入所删除道路的起点: ");
scanf("%s",start);
printf("请输入所删除道路的终点: ");
scanf("%s",end);
hbu.edges[searchSight(start)][searchSight(end)]=inf;
}
printf("\n\n\n\t\t\t删除成功!!\n\n");
system("pause");
system("cls");
}
int main()
{
int order=1,torder=1,aorder=1;// 主界面命令,游客界面命令,管理者界面命令
creat();
while(1)
{
system("cls");
Mmenu();
scanf("%d",&order);
if(order==1)
{
system("cls");
map();
while(1)
{
amenu();
scanf("%d",&aorder);
if(aorder==9)
{
printf("\n\n\n\n\t\t\t感谢使用!!\n\n\n") ;
break;
}
switch(aorder)
{
case 1://获取景点信息
{
GetSightInfo();
break;
}
case 2://求一个景点到其他景点的最短路径
{
ShortestPath();
break;
}
case 3://求两个景点之间的最短路径
{
TwoShortest();
break;
}
case 4://修改景点信息
{
changeSightInfo();
break;
}
case 5://增加景点
{
addSight();
break;
}
case 6://删除一个景点
{
deleteSight();
break;
}
case 7://增加道路
{
addEdges();
break;
}
case 8://删除道路;
{
deleteEdges();
break;
}
default:
{
printf("\n\n\n\n\t\t\t输入不合法!!");
system("pause");
system("cls");
}
}
}
}
else if(order==2)
{
system("cls");
map();
while(1)
{
tmenu();
scanf("%d",&torder);
if(torder==4)
{
printf("\n\n\n\n\n\t\t\t\t感谢使用!");
break;
}
switch(torder)
{
case 1://获取景点信息
{
GetSightInfo();
break;
}
case 2://求一个景点到其他景点的最短路径
{
ShortestPath();
break;
}
case 3://求两个景点之间的最短路径
{
TwoShortest();
break;
}
default:
{
printf("\n\n\n\n\t\t\t输入不合法!!");
system("pause");
system("cls");
}
}
}
}
else if(order==3)// 退出
{
system("cls");
printf("\n\n\n\n\t\t\t感谢使用!!");
return 0;
}
else //输入有误
{
printf("\n\n\n 输入不合法!\n");
system("pause");
}
}
}
番外篇
飞机大战小游戏
一个很简单的小游戏,在实验课上闲着没事写的
# include<stdio.h>
# include<windows.h>
# include<conio.h>
void chushihua();
void show();
void yhxiangguan();
void yhwuguan();
void HideCursor();
void gotoxy(int x,int y);
int high,wight;
int plane_x,plane_y;
int zidan_x,zidan_y;
int diji_x,diji_y;
int count=0;
int f=1;
char s='|';
int main()
{
chushihua();
while(1)
{
gotoxy(0,0);
HideCursor();
show();
yhxiangguan();
yhwuguan();
if(f==0)
break;
printf("得分:%d\n",count);
printf("1--切换激光炮\n");
printf("2--切换月牙炮\n");
printf("3--切换粒子炮\n");
}
system("cls");
printf("Game Over!!!\n得分:%d",count);
}
void chushihua()
{
high=20;
wight=30;
plane_x=wight/2;
plane_y=high/2;
zidan_x=-1;
zidan_y=plane_y;
diji_x=wight/2;
diji_y=1;
}
void show()
{
// system("cls");
int i,j;
for(i=0;i<high;i++)
{
for(j=0;j<wight;j++)
{
if(j==plane_x&&i==plane_y)
printf("*");
// else if(j==wight-1||j==0||i==high-1||i==0)
// printf("#");
else if(j==zidan_x&&i==zidan_y)
printf("%c",s);
else if(j==diji_x&&i==diji_y)
printf("@");
else
printf(" ");
}
printf("\n");
}
}
void yhxiangguan()
{
char input;
if(kbhit())
{
input=getch();
if(input=='w')
plane_y--;
if(input=='s')
plane_y++;
if(input=='a')
plane_x--;
if(input=='d')
plane_x++;
if(input==' ')
{
zidan_x=plane_x;
zidan_y=plane_y-1;
}
if(input=='1')
s='|';
if(input=='2')
s='^';
if(input=='3')
s='.';
}
}
void yhwuguan()
{
static int speed=0;
if(zidan_y>-1)
{
zidan_y--;
}
if(diji_y<high)
{
speed++;
if(speed==10)
{
diji_y++;
speed=0;
}
}
if(diji_y==high-1)
diji_y=1;
if(diji_y==zidan_y&&diji_x==zidan_x)
{
diji_y=0;
diji_x=rand()%20;
count++;
zidan_x=plane_x;
zidan_y=-1;
}
if(plane_x==diji_x&&plane_y==diji_y)
f=0;
}
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void gotoxy(int x,int y) //光标移动到(x,y)位置
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle,pos);
}