This is my first 文章。
今天我们学习了最基础的算法,最简单的排序
(一)稳定排序: a在b的前面,且a=b,排序后a还在b的前面,这就是稳定的排序
既然有稳定的那就肯定有不稳定的排序
不稳定排序:a在b的前面,且a=b,排序后a可能会出现在b的后面,这就是不稳定的排序
然后是内排序,外排序
(二)内排序:所有的排序操作都是在内存内完成的
外排序:数据太大,需要给数据存放到磁盘,通过数据传输,进行排序
(三)时间复杂度:程序运行时间,一个算法中语句执行的次数,记为T(n)
1.n是数据的规模
2.T就是函数比如T(n)=n^2+n*2+c
3.用大O阶来表示
4.时间的复杂度:O(1),O(n),O(logn),O(n^2),O(n^3)~~~O(n^k)
(四)空间复杂度
空间复杂度就是程序运行是所占的内存大小。
算法的时间复杂度和空间复杂度合称为算法的复杂度,他们往往是相互影响的,当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间;反之,当追求一个较好的空间复杂度时,可能会使时间复杂度的性能变差,即可能导致占用较长的运行时间,所以我们在编写程序或者代码的时间就需要考虑,算法的时间,数据所占空间的大小,还有算法描述语言的特性,算法运行的机器系统环境等各方面因素,才能够设计出比较好的算法。
(五)排序
1.冒泡排序
int main()
{
int a[250];
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
//冒泡排序
//从第一个开始比较,如果这个数比后面的大则交换位置,然后一直比较到最后,这时最后的就是最大的数
//,然后继续比较之前的数,还是2个比较从头开始,把最大的排到倒数第二个位置,然后,继续轮回一直比较
//到第一个数,
//本质:就是最大的数往下排
for(int i=n;i>0;i--)
{
for(int j=n;j>n-i+1;j--)
if(a[j]<a[j-1])
{
swap(a[j],a[j-1]);
}
}
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
2.选择排序
int main(){
int a[250];
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
//选择排序
//从第一个数开始寻找,先定义一个变量标记到第一个数的下面,两个两个比较,
//比较到最后找出最小或最大的数,然后变量一直标记最大或者最小的数,之后
//把第一个数给第最大的数交换位置,然后从第二个数开始找找出第二大的数,直至最后
//本质:找出最小的或最大的数,与第一个开始交换
for(int i=0;i<n;i++){
int dex=i;
for(int j=i+1;j<n;j++){
if(a[j]<a[dex])
dex=j;//dex永远指向最小的元素
}
swap(a[i],a[dex]);
}
for(int i=0;i<n;i++)
{
int dex=i;
for(int j=i+1;j<n;j++){
if(a[dex]<a[j])
dex=j;
}
swap(a[i],a[dex]);
}
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
3.插入排序
int main(){
int a[250];
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
//插入排序
//插入排序就是一个数组,从里面一个一个读,像起扑克牌一样一个一个起,起一张然后插入到
//你手中的牌中,从第二张开始。如果比第一张大则放到第一张的后面,然后第3张从第二张判断,
//如果比第二章大则放在后面,如果小则第二张往后放一个位置,然后判断与第一张的大小如果比
//第一张大则第二张就放你起的牌,如果没有第一张大,则第一张往后放一个位置,起的这张牌就
//放在第一个位置,这就是插叙函数,每次都从你手中最大的(或者最小)的开始判断,然后让这
//张你刚起的牌与你手中的牌中找到比他小的,然后让你手中比他大的往后移动一个位置,把这张牌插入进去
//本质:就是两个数组,一个无序,然后你手中的有序数组,每次从无序数组中拿出来一个数
//插入你手中的有序数组中,将他排序到你的数组中。
for(int i=1;i<n;i++){
int key=a[i];
int j=i-1;
while(j>=0&&key<a[j]){
a[j+1]=a[j];
j--;
}
a[j+1]=key;
}
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
4.重点 难点快速排序
int a[101],n;
//让我来试着解释一下这个快速排列,这个快排的本质就是,先找一个基数,然后比他大的放到这个数后面
//比这个数小的放到这个数的前面,然后前面的部分继续找一个基数,以此类推,然后找后面的部分,这个
//依次类推的过程是一个递归的过程(!这是一个重难点) 然后是如何进行找基数分类也是一个重点,
下面我先来举个例子给大家
6 1 2 7 9 4 5 10 8
我们为了方便就直接把这个数组的第一个数作为基数
然后标记一下,假设现在有连个士兵,一个是(士兵i)一个是(士兵j)
士兵i站在最左边,士兵j站在最右边 然后让士兵j开始向左移动找出比基数小的数,
然后士兵i再移动(为什么士兵j先移动这个很重要,需要大家思考)找出比基数大的数
之后交换这连个数的位置,5和7换位置
然后士兵j继续移动,直到i和j碰面,交换基数和当前i的位置
这是第一次排序分类,这时基数前的数都比基数小,基数后的数都比基数大
然后递归进入前面的部分和后面的部分传递参数值,继续按照这个方法排序
先给大家讲一下为什么士兵j必须先走,
举一个例子,
6 1 2 9 7
因为如果士兵i先走的话, 会停到9这个位置,然后士兵j在走直接就与i相遇了,然后交换i和基数的值,然后9被分配到了6的前面,
这是不对的!!!
所以说问题就存在与我们从哪边开始,如果从基数边开始这个士兵i就会停到比基数大的位置,然后与j相遇后和基数交换位置
这时这个士兵i占位置上的数确大于基数所以
从哪里开始查找很重要,一般是从基数的对面查找
然后递归的运用,有点难理解,就是你可以一次一次调用
但是每次调用都有两个门,这两个门都是会执行的
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(i+1,right);
}
int main()
{
int i,j,t;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
quicksort(1,n);
for(i=1;i<=n;i++)
printf("%d",a[i]);
getchar();getchar();
return 0;
}
//也可以直接从c++库中调用 sort(1,n);是1到n个数
bool cmp(int n,int m){
return n<m;//m>n是升序,m<n是降序
//c++库里的快排函数升序排列所以
//n<m的意思是从n到m
//m<n的意思是从m到n
}
int main(){
int a[105];
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n,cmp);
for(int i=0;i<n;i++)
cout<<a[i];
return 0;
}*/
这些都是我第一天上课所学,加上我对算法的理解写出来的,一起成长吧