和算法斗智斗勇
在经历了一周的算法大战后,总算摸到了算法的尾巴(虽然算法好像没有尾巴)接下来就总结一下我的收获:
1.对排序的回顾
对于排序算法的理解:
1.桶排序:需要一个数组三个变量,注意数组的大小为你要存元素的最大值
基本思想:将想要排序的数存放在数组里,初始化数组使每一个元素为0,然后用循环依次读入每一个数,然后数组中存放的为这个数字出现的次数,然后最后,将这个数组按照次数依次输出即可。
特别注意的点:
1.数组的初始化
2.在进行二次循环的话,要记得判断次数最少为1,次数为0的不输出。
#include<stdio.h>
int main()
{
int a[100]={0},i,j,t;//一个数组,三个变量 ,且完成初始化(for循环也可,但简化代码)
for(i=0;i<5;i++)//如果比较个数未知,那么就在设置一个变量n
{
scanf("%d",&t);//读入数据,并且数组中存的为次数
a[t]++;
}
for(i=0;i<=100;i++)//从小到大,如果从大到小,将数组反向遍历输出即可
{
for(j=1;j<=a[i];j++)//按照次数输出下标,但是要注意下标要大于等于1,不能为0
{
printf("%d",i);
}
}
return 0;
}
2.冒泡排序:需要一个数组,三个变量
基本原理:比较相邻的元素,假如第一个比第二个大,那么交换(从小到大),反之则是从大到小排。
需要注意的点:一共要比n-1躺,要注意数组越界问题
还有一点就是上下是配套的,假如数组从下标为1开始,那么所有下标都要为1,并且带等号,且二层循环不减一;
如果从0开始,那么都要从零开始,并且不带等号,二层循环减一(先记住,再理解)
#include<stdio.h>
int main()
{
int a[10],i,j,t,n;
scanf("%d",&n);//输入你想要比较的数字个数
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);//读入各个数字
}
for(i=0;i<n-1;i++)//比较n-1趟
{
for(j=0;j<n-i-1;i++)//当前这一位要比较多少趟
{
if(a[j]<a[j+1])//右小左大
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
for(i=0;i<n;i++)
{
printf("%d",a[i]);//遍历输出
}
return 0;
}
3.快速排序:需要一个数组和未知数n,还有left,right,两个指针型的东西,四个变量
#include<stdio.h>
int a[101],n;
void quicksort(int left,int right)
{
int i,j,t,temp;
if(left>right)
return;
temp=a[left];
i=left;
j=right;
while(i!=j)
{
while(a[j]>=temp&&i<j)
{
j--;
}
while(a[i]<=temp&&i<j)
{
i++;
}
}
if(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
a[left]=a[i];
a[i]=temp;
quicksort(left,i-1);
quicksort(j+1,right);
return;
}
重点是学会快速排序的调用!
2.序列的延伸(栈,队列,链表)
队列:队列是一种特殊的线性结构,它只允许在队列的首部进行删除操作,这称为出队,而在队列的尾部进行插入操作,这称为入队(首删尾入)
重点掌握:出队入队操作
#include<stdio.h>
int main()
{
int a[102]={0,6,3,1,7,5,8,9,2,4},head,tail;
head=1;
tail=10;
while(head<tail)
{
printf("%d",a[head]);//打印队首并出队,如果出队,直接指向首元素的那个类似于指针的东西++;
head++;
a[tail]=a[head];
tail++;//增添相同道理,只不过指向队尾的类似于指针的东西(也能理解为数组的下标)++
head++
}
return 0;
}
栈:
1.和队列的区别:
队列(Queue):是限定只能在表的一端进行插入和另一端删除操作的线性表
栈(Stack):是限定之能在表的一端进行插入和删除操作的线性表
队列:先进先出
栈:先进后出
用栈来判断回文数:
#include<stdio.h>
#include<string.h>
int main()
{
char a[101],s[101];
int i,len,mid,next,top;
gets(a);
len=strlen(a);
mid=len/2-1;
top=0;
for(i=0;i<mid;i++)
{
s[++top]=a[i];
}
if(len%2==0)
{
next=mid+1;
}
else
next=mid+2;
for(i=next;i<=len-1;i++)
{
if(a[i]!=s[top])
break;
top--;
}
if(top==0)
{
printf("YES");
}
else
printf("NO");
}
至少先记住,然后再理解不迟
链表:以前做过概述,不作详细解释
洛谷好题详解:
小南有一套可爱的玩具小人, 它们各有不同的职业。
有一天, 这些玩具小人把小南的眼镜藏了起来。 小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图:
这时singersinger告诉小南一个谜題: “眼镜藏在我左数第3个玩具小人的右数第11个玩具小人的左数第22个玩具小人那里。 ”
小南发现, 这个谜题中玩具小人的朝向非常关键, 因为朝内和朝外的玩具小人的左右方向是相反的: 面朝圈内的玩具小人, 它的左边是顺时针方向, 右边是逆时针方向; 而面向圈外的玩具小人, 它的左边是逆时针方向, 右边是顺时针方向。
小南一边艰难地辨认着玩具小人, 一边数着:
singersinger朝内, 左数第33个是archerarcher。
archerarcher朝外,右数第11个是thinkerthinker。
thinkerthinker朝外, 左数第22个是writewriter。
所以眼镜藏在writerwriter这里!
虽然成功找回了眼镜, 但小南并没有放心。 如果下次有更多的玩具小人藏他的眼镜, 或是谜題的长度更长, 他可能就无法找到眼镜了 。 所以小南希望你写程序帮他解决类似的谜題。 这样的谜題具体可以描述为:
有 nn个玩具小人围成一圈, 已知它们的职业和朝向。现在第11个玩具小人告诉小南一个包含mm条指令的谜題, 其中第 zz条指令形如“左数/右数第ss,个玩具小人”。 你需要输出依次数完这些指令后,到达的玩具小人的职业。
开始解答:
对于题目分析:首先小人有两个坐向,其次对于东西传的方向,也有区别,所以大致思路是,将其分为四类正向向左,反向向右,正向向右,反向向左,这样可以分为逆时针还是顺时针转动,从而达到目的,鉴于,有位置和名字两个变量,需用到结构体,具体代码如下:
#include<stdio.h>
struct {
int id; //记录坐向
char name[15];//记录名字
}stu[100000];
int next[][2] = { -1, 1, 1, -1 };//四种搭配,两种为逆时针正,两种为顺时针逆
int main() {
int n, m, i, ans, dir, num;
ans = 0;
scanf("%d %d", &n, &m);//n代表几个小人
for (i = 0; i < n; i++)
scanf("%d %s", &stu[i].id, stu[i].name);
for (i = 0; i < m; i++) {//m代表方向和步数
scanf("%d %d", &dir, &num);
ans += num * next[stu[ans].id][dir];
if (ans < 0)
ans = n - ((-1) * ans) % n; //将顺时针转的转化为逆时针转的
else if (ans >= n)
ans %= n; //如果大于一圈,那就取余
}
printf("%s", stu[ans].name);
return 0;
}
纯纯模拟题目,按照题目要求来就行。
以前做过的洛谷题复盘(p5717)
题目:给出三条线段 a,b,ca,b,c 的长度,均是不大于 10000 的整数。打算把这三条线段拼成一个三角形,它可以是什么三角形呢?
如果三条线段不能组成一个三角形,输出Not triangle;
如果是直角三角形,输出Right triangle;
如果是锐角三角形,输出Acute triangle;
如果是钝角三角形,输出Obtuse triangle;
如果是等腰三角形,输出Isosceles triangle;
如果是等边三角形,输出Equilateral triangle。
如果这个三角形符合以上多个条件,请按以上顺序分别输出,并用换行符隔开。
做题心得:
这道题不是很难,但是对于初学者来说很容易判断错条件和跳出循环的条件,最后不能ac
#include<stdio.h>
int main()
{
int a,b,c,tmp;//手动排序,C语言
scanf("%d%d%d",&a,&b,&c);
if(a>b){
tmp=a;
a=b;
b=tmp;
}
if(a>c){
tmp=a;
a=c;
c=tmp;
}
if(b>c){
tmp=b;
b=c;
c=tmp;
}//a<b<c
if(a+b>c){
if(a*a+b*b==c*c)//直角
printf("Right triangle\n");
if(a*a+b*b>c*c)//锐角
printf("Acute triangle\n");
if(a*a+b*b<c*c)//钝角
printf("Obtuse triangle\n");
if(a==b||a==c||b==c)//等腰
printf("Isosceles triangle\n");
if(a==b&&b==c)//等边三角形
printf("Equilateral triangle\n");
}
else printf("Not triangle\n");
return 0;
}
做题要点:就是要把三边大小判断好,并且以后再写题的时候注意条件结构嵌套的时候;有没有可能出现,特判隐含在补集中这种情况。
最后就是c语言了
1.宏定义
宏定义的要点:
1.定义时一定不能有分号;
2.宏定义如果嵌套使用必须按照后定义的那个;
3;宏定义只是简单的替换,不同于typedef
4.宏定义的#和##用法
5.宏定义可以用来写链表