• 【3】算法排序 (折半插入排序) (二分查找)


    二分查找

    思想:

    时间复杂度: O(log2n)

    // 二分查找
    // 基础版
    int BinarySearch(int * a, int l, int h, int find)
    {
            // a一定是有序的
            while(l<=h) {
                    int mid = (l+h)/2;
                    if (a[mid]==find) {
                            return mid;
                    } else if (find < a[mid]) {
                            h = mid - 1;
                    } else {
                            l = mid + 1;
                    }
            }
            return -1;
    }
    
    // 递归法
    int BinarySearch2(int * a, int l, int h, int find)
    {
            // if not while
            if(l<=h) {
                    int mid = (l+h)/2;
                    if (a[mid]==find) {
                            return mid;
                    } else if (find < a[mid]) {
                            return BinarySearch2(a, l, mid-1, find);
                    } else {
                            return BinarySearch2(a, mid+1, h, find);
                    }
            }
            return -1;
    }
    
    int main()
    {
            int a[10] ={1,4,5,6,7,8,12,15,33,39};
            BInsertSort(a, 10);
            int find = BinarySearch(a, 0, 10, 12);
            printf("find=%d
    ", find);
    
            int find2 = BinarySearch2(a, 0, 10, 12);
            printf("find2=%d
    ", find2);
            return 0;
    }

    折半插入排序(二分排序)

    思想:  

        在插入第i个元素时,对前面0 ~ i-1元素进行折半,先跟他们中间的那个元素比较,
             如果小了,则对前半再进行折半,否则对后半部分进行折半处理,直到left>right,然后
             再把第i个元素与目标位置之间的所有元素后移,再把第i个元素放在目标位置上。

    总结:比较已排序的序列中位数,不必像直接插入排序那样逐一比较,这个中位数将已排序的的部分再进行折半,再进行比较

    时间复杂度:

      O(n^2)

    和直接插入排序相比较,折半插入排序仅仅是减少了比较的次数,而移动总次数并没有发生改变。这个比较次数大概是
    O(nlogn)
    ,移动次数没有改变,所以其复杂度和直接插入排序是一样的
    O(N^{2})
    
    折半插入排序其实是在直接插入排序的基础上,
    结合了二分查找法的思想,顺序的二分查找替代了直接插入排序中遍历查找的过程,
    从而更快的能够确定待插入元素的位置,但是由于移动次数并没有发生改变,所以两者的时间复杂度相同。折半插入排序是稳定的,其时间复杂度为O(N^{2})
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void print(int * a, int n, int i)
    {
            printf("  %d: ", i);
            int j;
            for(j=0; j<n; j++) {
                    printf("%d ", a[j]);
            }
            printf("
    ");
    }
    
    void BInsertSort(int * a, int n)
    {
            int i, j, l, h, mid, tmp;
            // i=1 元素从第二个开始插入
            // i<n 下标从0开始 最后一个元素下标是n-1
            for(i=1; i<n; i++) {
                    l=0;
                    h=i-1;
                    tmp=a[i]; // 将被插入的元素,即乱序队列的第一个元素
                    while(l<=h) {
                            mid=(l+h)/2;
                            if(a[mid]>tmp) {
                                    h=mid-1;
                            } else {
                                    l=mid+1;
                            }
                    }
    
                    for(j=i; j>l; j--) {
                            a[j]=a[j-1];
                    }
    
                    a[l]=tmp;
                    print(a, n, i);
            }
    }
    
    void main()
    
            int a[8] = {21,3,7,9,39,20,8,4};
            BInsertSort(a,8);
    }
    ~                            

    做一个优秀的程序媛
  • 相关阅读:
    go channel select如何屏蔽已关闭通道
    go err
    在OneNote中快速插入当前日期和时间
    如何查看Isilon节点的硬件信息?
    一个可用来记录Isilon各个节点的CPU,网络,磁盘性能的命令
    Linux中如何查看文件夹的大小
    如何同步两台Linux机器的时间?
    Linux中的硬链接(hard link)和符号连接(symbolic link)
    在Cygwin里,如何进入到C盘?
    Remote Desktop Session中如何触发Ctrl+Alt+Delete?
  • 原文地址:https://www.cnblogs.com/oytt/p/13501819.html
Copyright © 2020-2023  润新知