• 排序(插入,冒泡与归并)——C语言


        写几个基础的算法,虽然很基础,但要是让我毫无准备立马写下还真写不顺畅,加上面试时候的紧张气氛,立马嗝屁。

    1.插入排序

    基本思想是将一个为排序元素插入到已排序的一系列元素中,关键点:1.找到元素应该处在的位置 2.插入元素

    sorted1 sorted2 sorted3 ........ undeter

    用链表实现会好一些,因为使用数组需要先移动一堆元素再插入,而链表直接插入即可,不过在C语言里使用链表得自己定义其实现和操作,比较麻烦(其实是我不大会),为了保护自己脆弱的自信心,这里就先简单用数组实现看看(实现递增排序)。

    void insertion_sort( int a[], int length )        /*length为数组长度*/

    {

        int i, j, key;

        for( i = 1; i < length; i++ )        /*将第一个元素a[0]视为已排序,因此从a[1]开始插入*/

        {

            key = a[i];        /*a[i]为待插入的元素*/

            j = i - 1;

            while( j >= 0 && a[j] > key )        /*向左找到第一个小于a[i]元素的位置*/

            {

                a[ j + 1 ] = a[j];        /*将大于a[i]的元素都向右移一位*/

                j--;

            }

            a[ j + 1 ] = key;        /*将a[i]的值插入到正确位置,位置j为第一个小于a[i]的元素*/

        }  

    }

    时间复杂度:O(n^2)

    2.冒泡排序

    基本思路是:每次比较相邻的两个数,小的在左,大的在右,最终每轮比较都得到一个最大的数。

    假设数组长度为len,那么最大的数就要放在a[len - 1], 第二大的数放在a[len - 2],以此类推。因此外层循环就是要从len-1~0,每次循环都得到一个最大的数。

    void bubble_sort( int a[], int length )

    {

        int i, j;

        for( i = length - 1; i > 0; i-- )

        {

            for( j = 0; j < i; j++ )        /*内循环比较相邻的两个数*/

            {

                if( a[j + 1] < a[j] )

                    swap( a, j, j + 1 );        /*自己定义一个元素交换函数*/

            }

        }

    }

    时间复杂度:O(n^2)

    3.归并排序

    基本思想:每个递归过程都对已排序的两个数组进行合并,在合并的过程中完成排序操作。

    具体实现:

    void merge( int a[], int start, int mid, int end )        /*先定义合并函数,作用是将数组中已排序的左右两部分按顺序合并*/

    {

        int n1 = mid - start + 1;
        int n2 = end - mid;
        int left[100], right[100];        /*这里如果用left[n1], right[n2]定义的话会报错,所以就用了固定长度的数组*/
        int i, j, k;
        for( i = 0; i < n1; i++ )
            left[i] = a[start + i];
        for( j = 0; j < n2; j++ )
            right[j] = a[mid + 1 + j];
        i = 0;
        j = 0; 
        for( k = start; i < n1 && j < n2; ++k )
        {
            if( left[i] < right[j] )

            {

                a[k] = left[i]; 
                ++i;
            }
            else
            {
                a[k] = right[j];
                ++j;
            }
        }
        if( i < n1 )
            for( ; i < n1; i++ )
            {
                a[k] = left[i];
                ++k;
            }
        if( j < n2 )
            for( ; j < n2; ++j )
            {
                a[k] = right[j];
                ++k;
            }

    }

    void merge_sort( int a[], int start, int end )        /*start与end分别为起始和终止位置*/

    {

        int mid;

        if( start < end )

        {

            mid = ( start + end ) / 2;

            merge_sort( a, start, mid );        /*对左半部分进行排序*/

            merge_sort( a, mid + 1, end );         /*对右半部分进行排序*/

            merge( a, start, mid, end );        /*合并两个排序的部分*/

        }

    }

    时间复杂度为O(nlogn)

  • 相关阅读:
    swift基本数据类型的使用
    宏定义单例类
    开发必备宏定义大全
    GUI02
    GUI01
    浅谈代码块的加载顺序
    Java里的多态
    在java中this和super的使用
    冒泡排序的简单优化
    命令行传参和不定传参
  • 原文地址:https://www.cnblogs.com/liangchao/p/2677712.html
Copyright © 2020-2023  润新知