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");
}