折半插入排序、冒泡排序、快速排序、简单选择排序、堆排序整理(介绍、原理、代码、时间复杂度)

很多人在学习数据结构时被排序所困扰,以下是我整理的五种排序总结(折半插入排序、冒泡排序、快速排序、简单选择排序、堆排序),包括代码、时间复杂度、应用场景等。

  1. 折半插入排序 (Binary Insertion Sort)
    • 原理:该算法是插入排序的一种优化版本。在普通的插入排序中,为了找到新元素的位置,我们可能需要线性搜索。但在折半插入排序中,我们使用二分查找来找到新元素的位置,从而减少比较次数。
    • 步骤:对于数组中的每一个元素,通过二分查找确定其应该插入的位置,然后将该位置及其右侧的元素后移,最后将新元素插入到正确的位置。
    • 时间复杂度:最坏情况下是O(n^2),但平均情况下,由于二分查找的优化,时间复杂度为O(n log n)
      // 折半插入排序函数  
      
      void insert_sort(int* array , int n){  
      
          int temp; // 用于暂存需要插入的元素  
      
           for(int i = 1; i < n; i++){ // 从第二个元素开始循环  
      
               int low = 0; // 左边界初始化为0  
      
               int hight = i-1; // 右边界初始化为当前元素的前一个位置  
      
               temp = array[i]; // 暂存当前元素的值  
      
               while(hight>=low){ // 当左边界小于或等于右边界时进行查找  
      
                   int mid = ( low + hight ) / 2; // 计算中间位置  
      
                   if (array[mid] > temp){ // 如果中间位置的元素大于要插入的元素  
      
                          hight = mid - 1; // 将右边界缩小到中间位置的左边  
      
                   }else{  
      
                       low = mid + 1; // 如果中间位置的元素小于或等于要插入的元素,将左边界扩大到中间位置的右边  
      
                    }  
      
                }  
      
                // 将找到的位置及其右侧的所有元素向右移动一位,为要插入的元素腾出空间  
      
                for (int j = i-1; j > hight; j--) {  
      
                    array[j+1] = array[j];  
      
                }  
      
                // 将找到的位置赋值给要插入的元素  
      
                array[hight+1] = temp;  
      
          }  
      
      }

  1. 冒泡排序 (Bubble Sort)
    • 原理:该算法通过重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
    • 步骤:通过不断地遍历数组,比较相邻的两个元素,若顺序错误则交换它们的位置。这个过程会重复进行,直到没有元素需要交换,即数组已排序完成。
    • 时间复杂度:最坏情况下是O(n^2),最好情况和平均情况下是O(n)
    • 代码:
// 冒泡排序函数  

void bobber_sort(int* array , int n){  

    int temp; // 用于交换元素的临时变量  

    for(int i=0;i<n;i++){ // 外层循环控制排序的轮数  

        for(int j=0;j<n-i-1;j++){ // 内层循环控制每轮排序的比较次数  

            if(array[j]>array[j+1]){ // 如果当前元素大于其相邻的下一个元素  

                temp=array[j]; // 临时存储当前元素的值  

               array[j]=array[j+1]; // 将当前元素的值设置为下一个元素的值  

                array[j+1]=temp; // 将下一个元素的值设置为临时存储的值,完成交换  

           }  

      }  

      }  

  }
  1. 快速排序 (Quick Sort)
    • 原理:使用分治法策略。选择一个基准元素,重新排列数组,使得基准的左侧都比基准小,右侧都比基准大。然后对基准的左侧和右侧分别递归进行这个过程。
    • 步骤:选择一个基准值,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均小于另一部分的关键字,然后分别对这两部分继续进行排序,以达到整个序列有序。
    • 时间复杂度:最坏情况下是O(n^2),但平均情况和最好情况下是O(n log n)
    • 代码:

// 快速排序函数  

void quick_sort(int* array , int low , int high){  

    int i = low, j = high; // 初始化两个指针,i指向数组的起始位置,j指向数组的末尾位置  

    int key = array[i]; // 选择数组的第一个元素作为基准值  

 

    while (i < j){ // 当两个指针没有相遇时,继续循环  

        while(i < j && array[j] >= key){ // 从右向左移动j指针,直到找到一个小于基准值的元素或j指针已经到了数组的起始位置  

            j--;  

        }  

        array[i] = array[j]; // 将找到的元素复制到i指针的位置  

 

        while(i < j && array[i] <= key){ // 从左向右移动i指针,直到找到一个大于基准值的元素或i指针已经到了数组的末尾位置  

            i++;  

        }  

        array[j] = array[i]; // 将找到的元素复制到j指针的位置  

    }  

    array[i] = key; // 将基准值放到正确的位置上  

 

    if (i-1 > low) { // 如果基准值左边的元素个数大于1,递归进行排序  

        quick_sort(array, low, i-1);  

    }  

    if (i+1 < high){ // 如果基准值右边的元素个数大于1,递归进行排序  

        quick_sort(array, i+1, high);  

    }  

}

  1. 简单选择排序 (Selection Sort)
    • 原理:在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。如此反复,直到所有元素均排序完毕。
    • 步骤:首先在未排序序列中找到最小元素,存放到已排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。如此反复,直到所有元素均排序完毕。
    • 时间复杂度:最坏和平均情况下是O(n^2)
    • 代码:

// 简单选择排序函数  

void select_sort(int* array , int n){  

    int i, j; // 循环控制变量  

    int min; // 待排序数组中最小值的下标  

    int tmp; // 临时变量,用于交换元素  

 

    for (i = 0; i < n - 1; ++i){ // 外层循环,控制排序的轮数,从0到n-2  

        min = i; // 假设当前位置的元素是最小的  

 

        // 内层循环,从当前位置的下一个元素开始,查找最小值的位置  

        for (j = i + 1; j < n; ++j){  

            if (array[j] < array[min]){  

                min = j; // 更新最小值的位置  

            }  

        }  

 

        // 如果找到了更小的值,则交换当前位置和最小值位置的元素  

        tmp = array[i]; // 临时存储当前位置的元素值  

        array[i] = array[min]; // 将最小值位置的元素值赋给当前位置  

        array[min] = tmp; // 将临时存储的值赋给最小值位置  

    }  

} // 简单选择排序结束
  1. 堆排序 (Heap Sort)
    • 原理:利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质(即子节点的键值或索引总是小于(或大于)它的父节点)。
    • 步骤:首先将无序数组构建成一个大顶堆(或小顶堆),然后将堆顶元素(最大值或最小值)与堆尾互换,之后将剩余的元素重新调整为大顶堆(或小顶堆),以此类推,直至整个数组有序。
    • 时间复杂度O(n log n)
      代码:
void swap(int* a, int* b) {//交换函数

    int tmp = *a;

    *a = *b;

    *b = tmp;

}



void maxheap_sort(int a[], int start,int end) {

    int c = start; // 当前(current)节点的位置

    int l = 2 * c + 1; // 左(left)孩子的位置

    int tmp = a[c]; // 当前(current)节点的大小

    for (; l <= end; c = l, l = 2 * l + 1) {

        // “l”是左孩子,“l+1”是右孩子

        if (l < end && a[l] < a[l + 1]) {

            l++; // 左右两个孩子中选择较大者,即m_heap[l+1]

        }

        if (tmp >= a[l]) {

            break; // 调整结束

        }

        else {// 交换值

            a[c] = a[l];

            a[l] = tmp;

        }

    }

}



void heap_sort(int a[], int n) {

    int i;

    // 从(n/2-1)--> 0 逐次遍历。遍历之后,得到的数组实际上是一个(最大)二叉堆

    for (i = n / 2 - 1; i >= 0; i--) {

        maxheap_sort(a, i, n - 1);

    }

    // 从最后一个元素开始对序列进行调整,不断地缩小调整的范围直到第一个元素

    for (i = n - 1; i > 0; i--) {

        // 交换a[0]和a[i]。交换后,a[i]是a[0..i]中最大的。

        swap(&a[0], &a[i]);

        // 调整a[0..i-1],使得a[0..i-1]仍然是一个最大堆。

        // 即,保证a[i-1]是a[0..i-1]中的最大值。

        maxheap_sort(a, 0, i - 1);

    }

}

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

温柔过了头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值