c語言學習之代碼

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









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章