1、贪心算法
//贪心算法装箱问题
#include<stdio.h>
#include<stdlib.h>
#define V 100
//物品体积
typedef struct
{
int gno;//物品编号
int gv;//物品体积
}ELE;
//物品结点
typedef struct goods
{
int vno;
struct goods * link;
}GOODS;
//箱子结点
typedef struct box
{
int remainder;//剩余体积
GOODS * hg;
struct box * next;
}BOX;
void printELE(ELE * head,int n)
{
int i;
for(i=0;i<n;i++)
printf("%d,%d\n",head[i].gno,head[i].gv);
}
void printBOX(BOX * head)
{
BOX * p=head;
int i=1;
while(p)
{
printf("\n第%d个箱子剩余%d\t",i++,p->remainder);
while(p->hg)
{
printf("这个箱子装了%d\t",p->hg->vno);
p->hg=p->hg->link;
}
p=p->next;
}
}
//降序排序
void sortD(ELE * g,int n)
{
int i;
int j;
ELE t;
for(i=0;i<n-1;i++)
for(j=0;j<n-i;j++)
if(g[j].gv<g[j+1].gv)
{
t=g[j];
g[j]=g[j+1];
g[j+1]=t;
}
}
//装箱
BOX * process(ELE * g,int n)
{
int i;
BOX * h=NULL,* t,* p,* k;
GOODS * q,* m;
for(i=0;i<n;i++)
{
q=(GOODS *)malloc(sizeof(GOODS));//先给物品分配
q->vno=g[i].gno;
q->link=NULL;
for(k=h;k&&k->remainder<g[i].gv;k=k->next);//没开箱子的情况,即K为NULL,或者找出能放下的第一个箱子
if(!k)//这里是一个箱子都没开
{
p=(BOX *)malloc(sizeof(BOX));//开箱
p->remainder=V;
p->next=NULL;
if(!h)//是不是第一个箱子
h=t=p;
else
t=t->next=p;//不是直接挂,t指向最后一个箱子
t->next=NULL;
p->hg=q;
p->remainder=V-g[i].gv;//放入物品
}
else//这个是有箱子,并且能放下
{
for(m=k->hg;m->link;m=m->link);
m->link=q;
k->remainder-=g[i].gv;
}
}
return h;
}
int main(void)
{
ELE * g=NULL;
BOX * b=NULL;
int i;
int n;
printf("请输入物品个数:\n");
scanf("%d",&n);
g=(ELE *)malloc(n*sizeof(ELE));
//输入物品数据
for(i=0;i<n;i++)
{
g[i].gno=i+1;
printf("请输入第%d个物品的体积:",i+1);
scanf("%d",&g[i].gv);
}
printELE(g,n);
sortD(g,n);
printELE(g,n);
b=process(g,n);
printBOX(b);
}
2、哈弗曼编码
//哈夫曼编码,利用结构体数组存储哈夫曼树
//用另一个结构体存储编码
#include<stdio.h>
#include<stdlib.h>
#define N 10
typedef struct
{
char word;//存储字符
int weight;
int left,right,parent;
}HuffNode;
typedef struct
{
int code[N];
int start;
}HuffCode;
void CreatHuffManTree(HuffNode * hn,int n)
{
int i;
int j;
int k1;
int k2;
for(i=0;i<n-1;i++)
{
k1=k2=-1;
for(j=0;j<n+i;j++)
{
if(hn[j].parent==-1&&k1==-1)
k1=j;
else if(hn[j].parent==-1)
{
k2=j;
break;
}
for(;j<n+i;j++)
if(hn[j].parent==-1)
if(hn[j].weight<hn[k1].weight)
{
k2=k1;k1=j;
}
else if(hn[j].weight<hn[k2].weight)
k2=j;
hn[n+i].weight=hn[k1].weight+hn[k2].weight;
hn[n+i].parent=-1;
hn[n+i].left=k1;
hn[n+i].right=k2;
hn[k1].parent=hn[k2].parent=n+i;
}
}
}
void CreatHuffManCode(HuffNode * hn,int n,HuffCode * hc)
{
int i;
int c;
int p;
for(i=0;i<n;i++)
{
c=i;
p=hn[c].parent;
hc[i].start=N;
while(p!=-1)
{
if(hn[p].left==c)
hc[i].code[--hc[i].start]=0;
else
hc[i].code[--hc[i].start]=1;
c=p;
p=hn[c].parent;
}
}
}
void printHuffManCode(HuffNode * hn,int n,HuffCode * hc)
{
int i;
int j;
for(i=0;i<n;i++)
{
printf("%c的编码是:",hn[i].word);
for(j=hc[i].start;j<N;j++)
printf("%2d",hc[i].code[j]);
printf("\n");
}
}
int main(void)
{
int i;
char c;
int w;
int leafcount;
HuffNode * hn;
HuffCode * hc;
printf("请输入叶子个数:");
scanf("%d",&leafcount);
hn=(HuffNode *)malloc((2*leafcount-1)*sizeof(HuffNode));
for(i=0;i<leafcount;i++)
{
printf("请输入第%d个叶子的信息:\n权值 字符 ",i+1);
scanf("%d %c",&w,&c);//先输字符回车被误判
//printf("权值:");
//scanf("%d",&w);
hn[i].word=c;
hn[i].weight=w;
hn[i].left=hn[i].right=hn[i].parent=-1;
}
CreatHuffManTree(hn,leafcount);
hc=(HuffCode *)malloc(leafcount*sizeof(HuffCode));
CreatHuffManCode(hn,leafcount,hc);
printHuffManCode(hn,leafcount,hc);
}
3、八皇后
//八皇后
#include<stdio.h>
int a[8]={0}; //存储第几列能不能放皇后
int b[15]={0}; //存储左上右下方向能不能放皇后
int c[15]={0}; //存储左下右上方向能不能放皇后
int x[8]={0}; //存储第几行的皇后放在第几个
void print(void)
{
int i;
int j;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if(x[i]==j)
printf("Q");
else
printf("*");
}
printf("\n");
}
}
void chess(int i)
{
int j;
for(j=0;j<8;j++)
{
if(a[j]==0 && b[i+j]==0 && c[i-j+7]==0)
{
a[j]=b[i+j]=c[i-j+7]=1;
x[i]=j;
if(i<7)
chess(i+1);
else
{
print();
printf("\n");
}
a[j]=b[i+j]=c[i-j+7]=0;
x[i]=0;
}
}
}
int main(void)
{
chess(0);
return 0;
}
4、判断左右括号匹配
//判断一个表达式的左右括号数目是否匹配
#include<stdio.h>
#include<string.h>
void main(void)
{
char exp[100];
int top=-1,i;
printf("请输入一个表达式:\n");
gets(exp);
for(i=0;exp[i]!=0;i++)
{
if(exp[i]=='(')
top++;
else if(exp[i]==')')
if(top>=0)
top--;
else
{
top--;
break;
}
}
if(top==-1)
printf("匹配!");
else
printf("不匹配!");
}
5、双向链表
//2013_2_26不带头结点的双向链表
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *pp,*fp;
}ElemPSN;
//创建双向链表
ElemPSN *CreateDlink(int a[],int n)
{
ElemPSN *head,*tail,*p;
int i;
//head是头结点指针,tail作为尾指针
head=tail=p=NULL;
for(i=0;i<n;++i)
{
p=(ElemPSN *)malloc(sizeof(ElemPSN));
p->data=a[i];
p->pp=p->fp=NULL;
if(i==0)
//判断是否为第一个结点
head=tail=p;
else
{
tail->pp=p;
p->fp=tail;
tail=p;
}
}
return head;
}
//正向输出该链表的数据域的值
void Aprintlink(ElemPSN *head)
{
ElemPSN *p;
for(p=head;p;p=p->pp)
printf("%5d",p->data);
}
//逆向输出该链表的数据域的值
void Bprintlink(ElemPSN *head)
{
ElemPSN *p;
for(p=head;p->pp;p=p->pp);
//两个for循环的终止条件不同
for(;p;p=p->fp)
printf("%5d",p->data);
}
//删除双向链表中值为val的结点
//假设没有重复值
//不需要两个指针联动,分头删、尾删、中间删
ElemPSN *DelNode(ElemPSN *head,int val)
//需要有返回值,否则有可能删掉head
{
ElemPSN *p,*q,*s;
//s,q分别作为p的前驱结点和后继结点
for(p=head;p&&p->data!=val;p=p->pp);
//寻找值为val的结点
if(!p)
printf("没有找到值为val的结点。\n");
else
{
q=p->pp;
s=p->fp;
if(p==head)
//分为三种情况
{
q->fp=s;
head=q;
}
else if(p->pp==NULL)
s->pp=q;
else
{
s->pp=q;
q->fp=s;
}
free(p);
}
return head;
}
//主函数
int main(void)
{
int a[]={10,20,30,40,50};
int val;
ElemPSN *head,*p;
//创建双向链表
head=CreateDlink(a,5);
//正向输出
Aprintlink(head);
printf("\n");
//逆向输出
Bprintlink(head);
printf("\n");
//删除值为val的结点
printf("请输入要删的值val:");
scanf("%d",&val);
head=DelNode(head,val);
//正向输出
Aprintlink(head);
printf("\n");
}
6、单向循环链表
//创建单向循环链表以及实现插入和删除
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
}ElemSN;
//单向循环链标的创建
ElemSN * CreateLink(int a[],int n)
{
ElemSN * head, * p,* tail;
int i;
for(i=0;i<n;++i)
{
p=(ElemSN *)malloc(sizeof(ElemSN));
p->data=a[i];
if(i==0)
head=tail=p;
else
tail=tail->next=p;
tail->next=head;
}
return head;
}
//输出单项循环链表
PrintLink(ElemSN * head)
{
ElemSN * p=head;
printf("单向循环链表的值为:\n");
do
{
printf("%5d",p->data);
p=p->next;
}while(p!=head);
}
//删除值为val的结点,假设无重复值
ElemSN * DelNode(ElemSN * head,int val)
{
ElemSN * p=head,* q=NULL;
do
{
if(p->data==val)
break;
q=p;
p=p->next;
}while(p-head);//也可以以q作为判断条件
/*可替换if为下
if(p==head&&q!=NULL)
printf("没有找到要删除的值!\n");
else
{
if(q==NULL)
{
for(q=p;q->next!=head;q=q->next);
head=p->next;
}
q->next=p->next;
free(p);
}
*/
if(p!=head)
{
q->next=p->next;
free(p);
}
else if(q==NULL)
{
for(q=p;q->next!=head;q=q->next);
q->next=p->next;
head=p->next;
free(p);
}
else
printf("没有找到要删除的值!\n");
return head;
}
//插入新结点s,假设有序
ElemSN * InsertNode(ElemSN * head,ElemSN * s)
{
ElemSN * p=head,* q=NULL;
do
{
if(p->data>s->data)
break;
q=p;
p=p->next;
}while(p-head);
if(q==NULL)
{
for(q=p;q->next!=p;q=q->next);
head=s;
}
s->next=p;
q->next=s;
return head;
}
//主函数
int main(void)
{
ElemSN * head,* s;
ElemSN x;
int a[6]={10,20,30,40,50,60};
int val,insert;
head=CreateLink(a,6);
PrintLink(head);
printf("\n");
printf("请输入要删除的值:\n");
scanf("%d",&val);
head=DelNode(head,val);
PrintLink(head);
printf("\n");
printf("请输入要插入的值:\n");
scanf("%d",&insert);
s=(ElemSN *)malloc(sizeof(ElemSN));
s->data=insert;
//s=&x;
//x.data=insert;
head=InsertNode(head,s);
PrintLink(head);
printf("\n");
}
7、万年历
//已知1900年1月1号是礼拜一,任意输入年月,打印出该月的日历
#include<stdio.h>
void main(void)
{
int i=1900,sum=1,k;//sum最终表示这月第一天是星期几,k表示这月有几天
int year,month;
printf("请输入大于1900年的年份:\n");
scanf("%d",&year);
printf("请输入月份:\n");
scanf("%d",&month);
for(;i<year;i++)
{
if((i%4==0&&i%100!=0)||i%400==0)//判断是润年
sum+=366;
else
sum+=365;
}
switch(month)
{
case 12 :sum+=30;
case 11 :sum+=31;
case 10 :sum+=30;
case 9 :sum+=31;
case 8 :sum+=31;
case 7 :sum+=30;
case 6 :sum+=31;
case 5 :sum+=30;
case 4 :sum+=31;
case 3 :
if((i%4==0&&i%100!=0)||i%400==0)//判断是润年
sum+=29;
else
sum+=28;
case 2 :sum+=31;
}
sum=(sum-1)%7+1;//+1算出这月第一天是礼拜几,第一列从礼拜天开始,因此第一天是礼拜几,就得打几次tab
printf("\n\t\t\t\t%d年%d月\t\t\t\t\n\n",year,month);
printf("\t日\t一\t二\t三\t四\t五\t六\t\n");
if(sum!=7)
for(i=0;i<sum;i++)
printf("\t");
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
k=31;
else if(month==2)
{
if((i%4==0&&i%100!=0)||i%400==0)//判断是润年
k=29;
else
k=28;
}
else
k=30;
for(i=1;i<=k;i++)
{
printf("\t%d",i);
if((sum+i)%7==0)
printf("\n\n");
}
printf("\n");
}
8、约瑟夫环
#include<stdio.h>
#define N 100
void main()
{
int a[N],m,n,k=0,j,i;
printf("请输入人数n:\n");
scanf("%d",&n);
printf("请输入正整数m:\n");
scanf("%d",&m);
printf("请输入各个人的密码:\n");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("出列顺序为:");
for(i=0;i<n;i++)
{
j=1;
while(j<m)
{
while(a[k]==0)
k=(k+1)%n;
j++;
k=(k+1)%n;
}
while(a[k]==0)
k=(k+1)%n;
printf("%4d",k+1);
m=a[k];
a[k]=0;
}
}
9、递归
//一些简单的递归的调用
#include<stdio.h>
int jiecheng1(int n)
{
int m=1;
n&&(m=n*jiecheng1(n-1));
return m;
}
int jiecheng2(int n)
{
if(n==0)
return 1;
else
return n*jiecheng2(n-1);
}
void erjinzhi1(int n)
{
if(n!=0)
erjinzhi1(n/2);
printf("%2d",n%2);
}
int lianjia(int n)
{
int m=0;
n&&(m=n+lianjia(n-1));
return m;
}
void nizhi(int n)
{
if(n!=0)
{
printf("%2d",n%10);
n=n/10;
nizhi(n);
}
}
int weihe(int n)
{
int m=0;
if(n!=0)
m=n%10+weihe(n/10);
return m;
}
int weimax(int n)
{
int m=0;
if(n!=0)
{
m=((m<=(n%10)?(n%10):weimax(n/10)));
}
return m;
}
int weishu(int n)
{
int m=0;
if(n!=0)
m=weishu(n/10)+1;
return m;
}
void print(int a[],int n)
{
if(n!=0)
{
printf("%5d",a[0]);
print(a+1,n-1);
}
}
void fanprint(int a[],int n)
{
if(n!=0)
{
fanprint(a+1,n-1);
printf("%5d",a[0]);
}
}
int arraysum(int a[],int n)
{
if(n==1)
return a[0];
else
return a[0]+arraysum(a+1,n-1);
}
void main(void)
{
int n=4;
int m=543210;
int a[10]={1,2,3,4,5,6,7,8,9,0};
printf("%d的阶乘是%d,%d!\n",n,jiecheng1(n),jiecheng2(n));
printf("%d的二进制是:",n);
erjinzhi1(n);
printf("\n%d的连加是%d!\n",n,lianjia(n));
printf("%d的逆置是:",m);
nizhi(m);
printf("\n%d的各个位之和是:%d\n",m,weihe(m));
printf("%d的位数是:%d\n",m,weishu(m));
printf("数组a的正向逆向输出是:\n");
print(a,10);
printf("\n");
fanprint(a,10);
printf("\n数组a的和是:%d\n",arraysum(a,10));
}
10、逆波兰表达式
//逆波兰表达式实现表达式的计算
#include<stdio.h>
#include<string.h>
int opl(char ch) //运算符的优先级判断
{
int op;
switch (ch)
{
case '*' :
case '/' : op=4;break;
case '+' :
case '-' : op=3;break;
case '(' : op=2;break;
case '@' : op=1;
}
return op;
}
long process(long x1,long x2,char ch) //将字符运算符应用成算术运算符
{
long op;
switch (ch)
{
case '*' : op=x2*x1;break;
case '/' : op=x2/x1;break;
case '+' : op=x2+x1;break;
case '-' : op=x2-x1;break;
}
return op;
}
void exchange(char pm[],char pa[]) //将中缀表达式转化为后缀表达式(逆波兰表达式)
{
char stack[10];
int top=-1;
stack[++top]='@';
while(*pm)
{
if(*pm=='(')
{
stack[++top]='(';
pm++;
}
else if(*pm>='0'&&*pm<='9')
{
(*pa)=(*pm);
pm++;
pa++;
}
else if(*pm=='+'||*pm=='-'||*pm=='*'||*pm=='/')
{
while(opl(*pm)<=opl(stack[top]))//栈外运算符优先级>栈顶运算符优先级,直接入
//反之,<=则先出,出完再入
*(pa++)=stack[top--];
stack[++top]=*(pm++);
*(pa++)=' ';
}
else if(*pm==')')
{
while(stack[top]!='(')
*(pa++)=stack[top--];
top--;
pm++;
}
else
pm++;
}
while(stack[top]!='@')
{
*(pa++)=stack[top--];
}
*pa=0; //给pa一个结束标志,注意不是赋值'0'
}
long complete(char a[])//对后缀表达式进行计算
{
long x1,x2,y,top=-1;
long stack[30];
while(*a)
{
if(*a==' ')
a++;
else if(*a>='0'&&*a<='9')
{
y=0;
while(*a>='0'&&*a<='9')
{
y=y*10+*a-'0'; //将字符转化为数字
a++;
}
stack[++top]=y;
}
else if(*a=='+'||*a=='-'||*a=='*'||*a=='/')
{
x1=stack[top--];
x2=stack[top--]; // 注意区分x1,x2的顺序
stack[++top]=process(x1,x2,*a);
a++;
}
}
if(top==0)
return stack[top];
else
return 0;
}
//判断括号匹配
int pipei(char exp[])
{
int i,top=-1;
for(i=0;exp[i]!=0;i++)
{
if(exp[i]=='(')
top++;
else if(exp[i]==')')
if(top>=0)
top--;
else
{
top--;
break;
}
}
if(top==-1)
return 1;
else
return 0;
}
//主函数
void main(void)
{
char m[100],a[100];
long record=0;
printf("请输入一个表达式:\n");
gets(m);
if(pipei(m))
{
exchange(m,a);
printf("后缀表达式为:%s!\n",a);
record=complete(a);
printf("这个表达式的值是%ld!\n",record);
}
else
printf("左右括号不匹配,无法计算!\n");
}