DS W9

http://47.99.57.28/problem/
//W8
//1847 B 表达式求值(栈和队列) //PRN
//1850 E 不同出栈情况(栈和队列)
//1852 -A 队列组合(栈和队列)
//2355 -F 稀疏矩阵相乘


/*

//W9 课后
//1870 C 根据上排给出十个数,在其下排填出对应的十个数(栈和队列)

//W9上机
//1863 G 求整数的各个组合之和(栈和队列)

*/

 (主函数搭配懒狗模板见文末)

1870 根据上排给出十个数,在其下排填出对应的十个数(栈和队列)

1 2 3 0 4 5 6 10 8 7
0 1 2 3 4 5 6 7 8 9

 

1 2 3 0 4 5 6 10 8 7
2 1 0 6 0 0 1 0 0 0

0 1 2 3 4 5 6 7 8 9
6 2 1 0 0 0 1 0 0 0

1861 约瑟夫环

如何使用指针需要关注

//1861 约瑟夫环 
#include <stdio.h> 
#include <stdlib.h>
typedef struct node{ int number; struct node * next;} person;

person * initLink(int n){
    person * head=(person*)malloc(sizeof(person));
    head->number=1;
    head->next=NULL;
    person * cyclic=head; int i; 
    for (i=2; i<=n; i++) {
        person * body=(person*)malloc(sizeof(person));
        body->number=i;
        body->next=NULL; 
        cyclic->next=body;
        cyclic=cyclic->next;}
    cyclic->next=head;//首尾相连
    return head;}

void findAndKillK(person * head,int k,int m){
 
    person * tail=head;
    //找到链表第一个结点的上一个结点,为删除操作做准备
    while (tail->next!=head) {tail=tail->next;}
    person * p=head;
    //找到编号为k的人
    while (p->number!=k) { tail=p; p=p->next;}
    //从编号为k的人开始,只有符合p->next==p时,说明链表中除了p结点,所有编号都出列了,
    while (p->next!=p) {int i;
        //找到从p报数1开始,报m的人,并且还要知道数m-1de人的位置tail,方便做删除操作。
        for (i=1; i<m; i++) {tail=p; p=p->next;}
        tail->next=p->next; free(p);//从链表上将p结点摘下来
        //printf("出列人的编号为:%d\n",p->number);
        p=tail->next;} //继续使用p指针指向出列编号的下一个编号,游戏继续
    //printf("出列人的编号为:%d\n",p->number);
    printf("%d",p->number); free(p);}
    
int main() { int n; scanf("%d",&n); //printf("输入圆桌上的人数n:");
    person * head=initLink(n);
    int k; k=1;//scanf("%d",&k); //printf("从第k人开始报数(k>1且k<%d):",n);
    int m; scanf("%d",&m); //printf("数到m的人出列:");
findAndKillK(head, k, m);}

1859 翻转单词顺序

注意清空字符数组;同时,EOF的数值为-1,应当用%d而不是%c来判断

#include <stdio.h>
#include <string.h>
#define N 40
//1859 C 翻转句子中单词的顺序(栈和队列)

int main(){
	char word[N], sentence[N][N]; int n, nums, i, j;
	A:
	while(scanf("%s", word)){
		int len=strlen(word);
		
     if(word[0]=='\"') 
{for(i=0; i+1<len; i++) word[i]=word[i+1]; word[len-1]='\"';}
else if(word[len-1]=='\"')
 {char temp[N]; strcpy(temp,word);
 word[0]='\"'; for(i=1; i<len; i++) word[i]=temp[i-1];
 strcpy(sentence[nums++], word); break;}		
		
		strcpy(sentence[nums++], word);
		//if(word[len-1]=='\"') break;
	}
	n=nums;
	for(i=n-1; i>0; i--) printf("%s ", sentence[i]);
	printf("%s\n",sentence[0]);
	
	for(i=0;i<N; i++) 
	for(j=0;j<N; j++)
	sentence[i][j]='\0'; 
	
	int d;
	if(scanf("%d",&d)!=EOF) goto A;
	else return 0;
}

1862 统计1出现的次数

//1862 F 在从1到n的正数中1出现的次数(栈和队列)
#include <stdio.h>
#define N 60 

void count_1(int n, int res[]) {int cnt=0, i=0, k=0;
	for(i=n; i>=0; i--) {
		int flag=0;
		int num=i;
		while(num){
			int r=num%10;
			if(r==1) {cnt++; flag=1;}
			num/=10;
		}
		if(flag==1) {res[k]=i; k++;}
		
	}
	printf("%d\n",cnt);
	for(i=0; i<k; i++) printf("%d ",res[i]);
}

int main(){
	int n, res[N]; scanf("%d",&n); 
	//int i=1; for(i=1; i<=n; i++) a[i]=i;
	count_1(n,res); //长度 
} 

1863 加法分解 REF 

(OJ有误还在检查,IS换成两个换行符就可以通过)

//1863 G 求整数的各个组合之和(栈和队列)
#include<stdio.h>   
#include<malloc.h> 
#include<string.h> 
#define SEN 100   

/*10
10
9 1
8 2
7 3
[7][2 1]这个有错误,应该把前面的也输出
6 4
[6][3 1]
5 4 1
4 3 2 1
*/ 

struct sqstack {char *base; char *top; int size;};   
      
struct sqstack *initEmptyStack(){   
    struct sqstack *p;   
    p=(struct sqstack *)malloc(sizeof(struct sqstack));   
    if(p!=NULL){   
        p->base=(char *)malloc(sizeof(struct sqstack)*SEN);   
        if(p->base!=NULL)   
        {   
            p->top=p->base;   
            p->size=SEN;   
            return p;   
        }   
    }   
    else free(p);    
}   
      
void push(struct sqstack *p,int a) { *p->top++=a;} 
  
void gettop(struct sqstack *p) {if(p->base!=p->top) return *(p->top-1); } 

int pop(struct sqstack *p) {return *(--p->top);}   
      
int main() {    
    struct sqstack *p1,*p2,*p3;
	int m,t=1,a,sum,n; scanf("%d",&m);
	p1=initEmptyStack(); //p1有序数列
	p2=initEmptyStack(); //p2存储结果
	p3=initEmptyStack(); //p3 
	printf("%d\n",m); n=m; //第一个 
	m--;
	while(m--) {sum=0;  
		t=1; do {push(p1,t); t++;} while (t<=m+1); //m=7 876543 2 1
		while(p1->base!=p1->top) {//依次对每个元素尝试 
			a=pop(p1); sum+=a; //printf("a=%d, sum=%d\n",a,sum);
			if(sum>n) sum-=a; //如果加上一个元素超出了,不加 
			else if(sum==n) //如果加上一个元素刚好,再次分解p2
			{//弹出p2存储到p3, 
			    //printf("a=%d, sum=%d\n",a,sum);
				while(p2->base!=p2->top) push(p3,pop(p2));
				while(p3->base!=p3->top) printf("%d ",pop(p3));
				printf("%d\n",a); sum-=a;
			}
			//如果加上一个元素还有空,要了,存到p2里面 
			else push(p2,a);
		}
		while(p2->base!=p2->top) pop(p2);
	}
}

2597 括号匹配 (改了一下帅哥的代码)

//2597 E 括号匹配
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
ElementType ERROR = 142857;
typedef enum {FALSE, TRUE} Boolean;
typedef struct {
	ElementType *data;
	int top;
	int maxSize;
} Stack;

//初始化操作,构造一个空栈
void InitStack(Stack *s, int maxSize){
	s->data = (ElementType *)malloc(maxSize * sizeof(ElementType)); 
	if (!s->data) exit(1);
	s->top = -1;
	s->maxSize = maxSize;}

//将栈清空
void ClearStack(Stack *s) {s->top = -1;}

//判断栈是否为空,若栈为空,则返回TRUE,否则返回FALSE
Boolean IsEmpty(Stack *s){
	if (s->top == -1) return TRUE;
	else return FALSE;}
	
//判断栈是否满,若栈满,则返回TRUE,否则返回FALSE
Boolean IsFull(Stack *s)
	{if (s->top >= s->maxSize - 1) return TRUE; return FALSE;}
	
//入栈操作,若栈s不满,则插入元素e到栈中并成为新的栈顶元素,返回TRUE;否则返回FALSE
Boolean Push(Stack *s, ElementType e){
	if (IsFull(s)) return FALSE;
	s->top++;
	s->data[s->top] = e;
	return TRUE;}
	
//出栈操作,若栈s非空,则删除s的栈顶元素,并用e返回其值,返回TRUE;否则返回FALSE
Boolean Pop(Stack *s, ElementType *e){
	if (IsEmpty(s)) return FALSE;
	*e = s->data[s->top];
	s->top--;
	return TRUE;}
	
//获取栈顶元素,若栈s非空,则返回s的栈顶元素,栈顶指针保持不变;否则返回ERROR
ElementType GetTop(Stack *s){
	if (IsEmpty(s)) return ERROR;
	return s->data[s->top];}

//检验表达式中所含括号是否正确匹配,正确则返回TRUE,否则返回FALSE
Boolean ParenthesisMatchingChecker(char exp[]){
	Stack s; ElementType e; int flag = 1; int i = 0; InitStack(&s, 100);
	while (exp[i] != '\0' && flag){
		switch (exp[i]){
			case '(':
			case '[': 
			case '{':Push(&s, exp[i]);	break;	//若是左括号压栈
			case ')': //若是“)”,则根据当前栈顶元素的值分情况考虑
				//若栈非空且栈顶元素是“(” //正确匹配,弹出栈顶元素
				if (!IsEmpty(&s) && GetTop(&s) == '(') Pop(&s, &e);
				else flag = 0;	break;	//否则,匹配失败,置标志位flag为0
			case ']':
				if (!IsEmpty(&s) && GetTop(&s) == '[') Pop(&s, &e);
				else flag = 0; break;
			case '}':
				if (!IsEmpty(&s) && GetTop(&s) == '{') Pop(&s, &e);
				else flag = 0; break;
		}
		i++; //继续读入下一个字符
	}
	if (IsEmpty(&s) && flag) return TRUE;	//若栈空且标志位flag为1,则匹配成功,返回TRUE
	else return FALSE;				//否则匹配失败,返回FALSE
}

int main(){
	int t; char c; scanf("%d%c",&t,&c);
	while(t--){
		char exp[1000]; scanf("%s", exp);
	if (ParenthesisMatchingChecker(exp)) printf("Yes\n");
	else printf("No\n");} }

1869 删除字符数组中的特定字符

#include <stdio.h>
#include <string.h>
#define N 100

int In(char a[], char e){int i=0, len=strlen(a);
	for(i=0; i<len; i++) if(a[i]==e) return 1; return 0; }

//1869 B 在字符串中删除特定的字符(栈和队列)
//使用额外存储数组的这个方法比较容易出错
//前一个方法利用率缓冲输入输出的特征直接输出,对了
int main() {int i=0;
	char a[N]; gets(a); int len_a=strlen(a);
	char b[N]; gets(b); int len_b=strlen(b);
	for(i=0; i<len_a; i++) if(!In(b,a[i])) putchar(a[i]);}

1858 两数之和为指定值

#include <stdio.h>
#define N 50

int main(){
	int a[N], i=0, j=0; char temp;
	while(scanf("%d%c",&a[i],&temp)) {i++; if(temp=='\n') break;}int n=i;
	int sum; scanf("%d",&sum);
	
	for(i=0; i<n; i++)
	for(j=i+1; j<n; j++)
	if(a[i]+a[j]==sum) {printf("%d %d",a[i],a[j]); break;}
	//for(i=0; i<n; i++) printf("%d ",a[i]);} 
//这题可能关键在于处理输入输出的问题,之前用的是scanfEOF,这里用的是%d%c判断
//要注意缓冲区系统的问题

1857 输出k个最小的数字

//1857 A 查找最小的k个元素(栈和队列)
//Len函数有时候有问题,还是直接带个长度参数进去吧
#include <stdio.h>
#define N 50
void Swap(int *a, int *b) {int t=*a; *a=*b; *b=t;}

void Sort(int a[], int n){
	int i=0, j=0; for(i=0; i<n; i++)
	for(j=0; j<n-1-i; j++)
	if(a[j]>a[j+1]) Swap(&a[j], &a[j+1]);
}

int main(){
	int n, k, a[N]; scanf("%d %d",&n, &k);
	int i=0; for(i=0; i<n; i++) scanf("%d",&a[i]);
	Sort(a,n); for(i=0; i<k; i++) printf("%d ",a[i]);
} 

1878 Ackerman函数 REF

#include <stdio.h>
int Akm(int m, int n){
	if(m==0) return n+1;
	if(m!=0 && n==0) return Akm(m-1,1);
	return Akm(m-1,Akm(m,n-1));
}

int main(){int m, n; 
    scanf("%d %d",&m,&n);
	printf("%d", Akm(m,n));}

1871 丑数

//1871 D 丑数(栈和队列)
//只包含因子2、3和5
int isUgly(int a){
	//int beauty=[5,7];
	if(a%5==0) return 0;
	if(a%7==0) return 0;
	return 1;}

int main() {int n; scanf("%d", &n);
	printf (isUgly(n) ? "YES":"NO");}

1860 第一个只出现一次的字符

#include <stdio.h>
#include <string.h>
#define N 40

void cnt_only(char a[]){
	int i=0, j=0, len=strlen(a); //char b[N];
	//只出现一次的 第一个 
	for(i=0; i<len; i++){ int cnt=0;//判断是否有重复 
		for(j=i+1; j<len; j++) if(a[i]==a[j]) cnt++;//有重复
		//printf("a[%d]=%c, cnt=%d\n",i,a[i],cnt);
		if(cnt==0) {printf("%c", a[i]); break;}}}

//1860 D 在字符串中查找第一次出现的字符(栈和队列)
int main(){char a[N]; gets(a); cnt_only(a);}

1868 A 调整数组顺序使奇数位于偶数前面(栈和队列)

int main() {int odds=0, evens=0;
	int a[N]={0}, len_a=0, i=0; static int odd[N], even[N];
	while(scanf("%d",&a[len_a])!=EOF)  len_a++;
	//printf("a:"); Prints(a);
	for(i=0; i<len_a; i++)
	if(isEven(a[i])){
		even[evens]=a[i];
		evens++;
	}else{
		odd[odds]=a[i];
		odds++; }
	//printf("odd:"); Prints(odd);
	//printf("even:"); Prints(even);
	Sort(odd); Sort(even); 
	Reverse(odd); Print(even);
}


 懒狗模板

//bokuwa_langou_des.h

#include <stdio.h>
#include <stdlib.h>
#define N 30

int Len(int a[]) {int len=0; while(a[len]!=0) len++; return len;}

void Swap(int *a, int *b) {int t=*a; *a=*b; *b=t;}

void Sort(int a[]){
	int i=0, j=0, len=Len(a);
	for(i=0; i<len; i++)
	for(j=0; j<len-i-1; j++)
	if(a[j]>a[j+1]) Swap(&a[j], &a[j+1]);}

void Clear(int a[]) {int i=0, n=Len(a);
	for(i=0; i<n; i++) a[i]=0;}

void Reverse(int a[]) {int i=0, n=Len(a);
	for(i=n-1; i>=0; i--) printf("%d ",a[i]);}

void Print(int a[]) {int i=0, len=Len(a);
    if(len==0) return;
	for(i=0; i<len; i++) printf("%d ",a[i]);}

void Prints(int a[]) {int i=0, len=Len(a);
    if(len==0) {printf("\n"); return;} 
	for(i=0; i<len; i++) printf("%d ",a[i]);
	printf("\n");}

int isEven(int a)
	{if(a%2==0) return 1; else return 0;} 

int Scanf_EOF(int a[]){ int len=0;
	while(scanf("%d", &a[len])!=EOF) len++;
	return len;}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值