学习心得:
学期近末,已经到了大学第一学期的结束。我学习c语言不知不觉三个月了。学习了数据的基本类型,条件从句,循环等从句,到了c语言中重点也是比较难的一部分——数组。
数组的练习题是第一套让我卡这么久的练习题,直到写下这此博客的时间,我的oj上的题依旧有两个等待着我去攻克。在攻克那最后两个题之前的几个题一度让我消沉。看着一个个的提交过去的同学们,我不禁有种想要放弃并且去网上找答案的冲动。
或许也是这么久不间断的学习以及我那稍稍领先的进度让我怠惰,我的学习进度慢了很多。一个星期只打那么一两次代码也是常有的事情。每次打开题目界面,那密密麻麻的文本仿佛在叫嚣着让我放弃,一种排斥的感觉从心底慢慢腾满我的胸腔,我只能将自己沉浸在高数之中麻木自己。
acm新生赛结束,即使过得去的成绩进一步激励了我,我仍然存在这种排斥的感觉。但是我想,这种排斥或许是弥漫在大多数同学门的内心之中,无论学习好坏,我们都无法避免滋生出消极的情绪,学习的过程可能就是这种克服消极情绪并一步步让自己变得坚强的过程。学习到的内容倒是学习目的的其次。
所以,我希望看到这里的同学们,无论你现在是学习到了什么进度或者在人生的哪个阶段,我们都要努力的去适应这种永远都存在艰辛的生活。正是这种生活迫使我们走出舒适区,进一步挑战自己。使自己变得内心强大。共勉。
数组基础知识:
数组:顾名思义,一组一组的数存在一个首地址下,是一组具有相同类型的变量的集合。可以存放多个数据值。这个集合的名字就叫做数组名,构成数组的数据叫做数组元素。一般来说我们要访问(输入、输出)数组元素,需要通过数组下标来完成我们的操作。并且,数组一旦被定义大小便不再改变。
一维数组的定义:
数组类型 数组名[元素个数];
注意:数组下标不是从我们熟悉的1开始。而是从零开始。所以设置数组下标时最好设大十个,以免调用时从零开始调用,使数组越界,出现run time error(这个错误出现的一般是因为三个原因:数组越界,指针越界,分母为零,数组开的太大)的错误。
数组在定义时,数组下界不能是变量。
数组的赋值,一般是利用for循环来逐个赋值。但在数组清零时,可以利用for循环一个个清零,也可以利用memset(a,0,sizeof(a))*来清零。
*memset将某一内存的前n个字节全部设为中间的指定的ASCII码的值。 头文件:<memory.h>或者<string.h>。 初始化通常为0或者‘/0‘;
n维数组的定义:
数组类型 数组名[下标][下标][下标]······;
二维数组中,{例如int a[5][6];}第一个下标表示数组有几行(5),第二个下标表示一行之中的第几列(6)。
所占字节数:
一维数组:数组长度*sizeof。
二维数组:第一维长度*第二维长度*sizeof。(sizeof大小与机器字长有关)。
因为类型所占的字节确定,所以二维数组所开的下标大小不能太大,一维数组相较于二维略大一些。
数组的声明:
二维数组中第一维长度声明可以省略,第二维长度不可以省略。这是因为在c++中,数据按行存放,一行满了存到下一行,所以只要知道一行存放多少个,就推断出需要开几行的内存。
字符串 :
字符串是由一个个字符构成的。所以可以设置一个字符数组来存放一个个字符,从而达到存放一个字符串的作用。所以字符串的输入的六种方法如下:
1.按%c格式符一个个单独输入输出:
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
char a[100];
for(int i=1;a[i]!='\0';i++) //一般来说字符串大小未知,用‘/0’来判断是否结束
{
scanf("%c",&a[i]); //或者使用cin>>a[i]也可以。
}
for(int i=1;a[i]!='\0';i++)
{
printf("%c",a[i]);
}
return 0;
}
2 . 按%s格式符,将字符串作为一个整体输入输出。
scanf("%s",a);//这里a不再需要写下标,注意字符长度+1不要超过下标大小即可。并且不需要取址符&
printf("%s"a);
这里输入不能输入空格,空格与回车均表示输入结束。
3 . 用gets()输入。用puts()输出。
gets(a);//同样不需要写下标
puts(a);//遇到'\0'输出结束并自动输出一个换行。
gets()以回车为终止符,可以读入空格。同时回车将被从缓冲区读走,不作为字符串一部分。而scanf()不读走回车,仍然停留在缓冲区中,容易引起不知名错误(还不知道什么错误但是肯定有问题!!qwq)
头文件include<cstdio>
3.getchar(),putchar()一个字符
使用举例:
ch=getchar();
putchar(ch);
4.getline()
需要<cstring>或者<string.h>头文件。
(哈哈哈还不是很会用等我会了再补充)
5.cin.getline()
6.cin.get()
(嗯···没有错我都没有用过,等我会了再补充。)
排序:
1.冒泡排序:
两个两个比较排序,(若降序)每比较一次小的那个将移动至后面一个,那么第一次循环,最小的那个将移动至最后面,每循环一次,都会有一个相较于前面部分最小的移动到最后面。若有n个数,最多循环n-1次,就可以变为完全有序。
代码实现:
#include<iostream>
using namespace std;
int main()
{
int n,a[100];
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n-1;i++)
{
for(int j=i+1;i<=n-1;j++)
{
if(a[j]>a[j+1]) //升序
swap(a[j],a[j+1])
}
}
return 0;
}
2.选择排序:
遍历一遍,(若升序)将后面最小的与第一个交换。之后进行第二次遍历,选第二个为基准,后面最小的与第二个进行交换。也需要n-1次循环。
int a[100];//假装有数,并且有n个。
int k;
for(int i=0;i<=n-1;i++)
{
k=i;
for(int j=i+1;j<=n;j++)
{
if(a[i]<a[j])
k=j;
}
if(k!=i)
swap(a[i],a[k]);
}
3.插入排序:
一个个插进已经有序的数列之中,直到插完所有的数。
int a[100],n; //n个数。
for(int out=1;out<n;out++)
{
int temp=a[out];
int in=out;
while(in>0&&temp<a[in-1])
{
a[in]=a[in-1];
in--;
}
a[in]=temp;
}
4.桶排序:
数据必须有明显的范围限制,且最好数据之间有所重复。
int a[11],t;
for(int i =1;i<11;i++)
{
cin>>t;
a[t]++;
}
for(int i =1;i<11;i++)
for(int j =1;j<=a[i];j++)
cout<<i;
//从出现至少1次的数开始,输出a[i]出现次数的i;
//例如。出现了a[2]=4;
//输出2222
5.sort()排序:
简单易行,需要<algorithm>头文件。
sort(a,a+n) //排序下标0~n-1;a[n]无意义。默认升序
sort(a,a+n,cmp)
int cmp(int x,int y)
{
return x>y;
}
//实现降序排列
6.其他排序方法
嗯···等我成为一个大佬,再做补充。
查找:
1.顺序查找
一个个遍历查找,与想要查找的数据对照,若相等则查找成功,无相等项则查找失败。
int k;//设k为待寻找的数值。
bool m=false;
for(int i=1;i<=n;i++)
{
if(a[i]==k)
m=true;
}
2.二分查找(折半查找)
相当于翻书一样,一半一半的减去不需要的部分,直到找到想找到的值。前提:已经有序。
代码实现:
int zuo=1,you=s,mid;
int k;//待查找数值。
while(zuo<=you)
{
mid=(zuo+you)/2;
if(a[mid]==k)
{
cout<<"yes";
return 0;
}
else if(a[mid]>k)
you=mid-1;
else if(a[mid]<k)
zuo=mid+1;
}
cout<<"no";
3.其他查找方法
听学长讲过lower_bound()和upper_bound()这两个查找函数(好像也算是二分查找不过我还没理解这个,暂时放在这里面面吧),还不是很了解。
还有那什么哈希,分块查找(好像还有什么分块排序···)日后补充。
有问题欢迎大家补充!
辛苦你耐心的看完,这个好像应该放在最少三个个不同的博客里面啊哈哈···再说=w=。