数据结构-杂记--选择排序

本文介绍了C语言中动态内存分配的基本概念与实践,并详细解释了选择排序算法的工作原理及其实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 动态存储空间
    • c语言允许在程序运行时,进行存储空间的分配,这段空间就是系统堆;
    • 通常申请动态内存空间使用的函数是malloc,函数在系统空闲内存空间中分配到合适的空间后,返回这段空间的首地址,也就是这种类型的指针值,在进行内存空间的申请时,需要指定数据空间的类型,如果函数分配空间失败,那么返回值就是NULL
#include<stdio.h>
#include<stdlib.h>

int main(){
    int *pi=NULL;
    float *pf=NULL;
//内存空间申请时,必须指定数据类型;
    pi=(int *)malloc(sizeof(int));
    pf=(float *)malloc(sizeof(float));

    *pi=11;
    *pf=12.34;

    printf("The data is %d:\n",*pi);
    printf("The float is %f:\n",*pf);
//在进行内存空间释放时,不需要指定类型;
    free(pi);
    free(pf);
}
  • 在进行空间的申请时,失败的概率也是很大的,所以需要判断空间是否申请成功;
if((pi=(int*)malloc(sizeof(int)))==NULL)
    sprintf(stderr,"Insufficient memory");
  • 在进行内存空间的申请后,一定需要进行空间的释放,否则程序就是异常的;
  • 由于系统之间的差异,在进行空间申请时,即使指定了数据类型,还是建议进行指针类型的强制转换;
pi=(int*)malloc(sizeof(int));
  • 算法的一些知识:
    • 定义:算法是指令的有限集合,按照顺序执行这些指令,可以完成特定的任务;
    • 算法需要遵循几种原则:
      • 1.输入:算法必须是可以处理一个或者几个有限个数据;
      • 2.输出:算法是需要产生一定的输出的;
      • 3.确定性:算法必须在确定的输入,可以得到确定的输出;
      • 4.有限性:算法必须在可接受的时间内执行完成;
      • 5.有效性:算法的每一步都必须是可执行的,也就是在理论和实践中是可行的;
  • 先介绍关于数值交换:
void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
  • 在进行数值交换时,一定是需要对指针进行操作的,否则结果在本质上是不会发生改变的,数值交换也可以使用宏来实现;
#define SWAP(x,y,t) ((t)=(x),(x)=(y),(y)=(t))
  • 接下来实现一个简单排序算法:
  • 选择排序
#include<stdio.h>
#include<stdlib.h>
//需要借助上面的数值交换的过程;
void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

void choice_sort(int array[], size_t size_of_array)
{
//选择排序关于简单的异常的处理;
    if(array==NULL||size_of_array==0||size_of_array==1){
        exit;
    }
    size_t i = 0, j = i, min = 0;
    size_t k=0;
//在进行循环遍历时,i的值不可能是负数,所以不建议使用int来定义;
    for (i = 0; i < size_of_array - 1; ++i)
    {
        min = i;
        for (j = i + 1; j < size_of_array; ++j)
        {
//使用内层循环的j来遍历未排序序列的数值,比较是否比当前假设的数值小,如果小,修改下标为当前下标值;
            if (array[j] < array[min])
                min = j;
        }
//对于上述的比较结果,使用swap函数进行交换;
        swap(&array[i], &array[min]);
//这里将每次交换的的结果进行简单的输出;
        for(k=0;k<size_of_array;++k)
            printf("%d\t",array[k]);
        printf("\n");
    }
}


int main()
{
    int array[] = {4, 7, 9, 3, 5, 1, 6};
    choice_sort(array, sizeof(array) / sizeof(int));
    size_t i = 0;
    for (i = 0; i < sizeof(array) / sizeof(int); ++i)
        printf("%d\t", array[i]);
}
  • 程序执行结果:
    这里写图片描述

*选择排序动态图(借别人的一张图):
这里写图片描述

  • 对于选择排序的分析:
    • 1.假设按照从小到大进行排序,一开始是乱序的,首先使用一层for循环来进行遍历元素,并且假定当前元素是最小的;
    • 2.第二层for循环从第一层for循环假设元素的下一个元素来进行遍历,并且和已知的假设最小元素进行比较,满足就进行交换;
    • 3.一直到第一层循环遍历到倒数第二个元素停止,因为最后一个元素是不用进行比较的;
    • 4.选择排序算法的时间复杂度是O(n^2)
    • 了解一下算法的稳定性:
      • 1.算法的稳定性表示的是,在具有重复元素的序列里面,排序前后两个或者几个相同元素的相对顺序是否发生改变;
      • 假设序列1,5a,8,0,4,7,5b,9,0,假设5a5b表示的都是5这个元素,排序之后的结果如果是0,0,1,4,5a,5b,7,8,9,这个算法就是稳定的,当然这这里的意思是所有的重复元素的相对顺序都不发生改变,只要有一组员素发生改变,都不属于稳定的排序算法,相反不稳定的排序算法的结果就是0,0,1,4,5b,5a,7,8,9;
      • 首先选择排序属于不稳定的排序算法,应该这样进行分析:
        *假设已知序列为1,5a,8,0a,9,7,5b,4,0b手写一下排序的过程应该是这样的:
        选择排序不稳定性
        *按照上面的排序过程5a5b的相对位置已经发生改变,所以可以证明选择排序是不稳定的算法;
        选择排序的C++实现:

#include<iostream>

using namespace std;
//T 这里使用了模板编程的函数编程的一点知识,T的类型可以跟据已经传递参数的类型自动进行推导可以处理int,float,double等常见类型,代码的复用性要比单纯定义int一种类型的更好,这也是模板编程的优势;
template<class T>
//这里不在使用指针,使用C++语言的引用来进行处理,对应于引用是必须绑定一个相同类型的对象的,引用不应该为空;
void myswap(T &left, T &right)
{
//添加一些异常处理的判断
    if(left==right)
    exit;
    T temp;
    temp = left;
    left = right;
    right = temp;
}

template<class T>
void Choice_sort(T array[], size_t sizeof_array)
{
     T min;
     for(size_t i=0;i<sizeof_array-1;++i){
         min=i;
         for(size_t j=i+1;j<sizeof_array;++j){
             if(array[j]<array[min])
                 min=j;
         }
         myswap(array[i],array[min]);
     }
}

int main()
{
    int array[]={5,5,3,2,1,6,7,4,3,9,1,3,0};
    Choice_sort(array,sizeof(array)/sizeof(int));
    for(auto X:array)
        cout << X << " ";
    cout << endl;

}
  • 建议使用C++的代码进行验证;
  • 上面描述的遍历都是从前往后进行遍历的,其实从后往前也是可以进行遍历的,实现也不是很难,建议可以试一下;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值