排序

2020.8.26    排序算法

一.简单模板

1.选择排序:时间复杂度o()

每次找到最小的一个,然后与没排的第一个元素交换

void choseSort(int arr[], int n) {

    int i, j;

    int min, temp;

    // 每次从未排序的部分选出一个最小的元素,最后一次只剩一个元素未排序

    // 此时实际上已经排好序,故只需要n-1次外层大循环

    for (i = 0; i < n - 1; ++i) {

        min = i;    // 假定未排序部分的第一个元素为最小的元素

        // 遍历剩下的部分,找到最小的元素

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

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

                min = j;

            }

        }

        // 如果第一个元素就是最小的元素,就不需要交换了

        if (min != i) {

            temp = arr[i];

            arr[i] = arr[min];

            arr[min] = temp;

        }

    }

}

 

2.冒泡排序:时间复杂度o()

一步一步来,每个元素都只跟他后面一个比,大于就交换,任务就是将每一个元素送到末尾。但是存在有可能几轮就排序好了,但是还在比较,所以增加flag元素单标此次循环比较有没有移动。

 代码:

void bubblingSort(int arr[], int n) {

    int i, j, temp;

    int flag = 0;   // flag用来校验每轮循环有没有移动元素,0为没有移动,1为移动

    // 每次将一个元素送到末尾,n个元素,执行n次

    for (i = 0; i < n; ++i) {

        flag = 0;

        // 之前的循环已经将i个元素送到末尾,不需要再次比较,故减去,因为跟后一个元素比较,为了避免溢出,故减一

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

            // 如果当前的元素比后一个元素小,就交换

            if (arr[j] > arr[j + 1]) {

                flag = 1;   // 有数据交换

                temp = arr[j];

                arr[j] = arr[j + 1];

                arr[j + 1] = temp;

            }

        }

        // 没有数据交换,提前结束

        if (flag == 0) {

            break;

        }

    }

}

 

3.插入排序     时间复杂度o()

将一个数放到一个有序队列中,从末尾开始一个个比较,大于往后移,直到找到合适的位置。

代码:

void insert_sort(int arr[], int len)
  {
    for (int i = 1; i < len; ++i)
    {
      if (arr[i] < arr[i - 1]) {
      int temp = arr[i];
      int j = i - 1;
      for (; j >= 0 && arr[j]>temp; --j) {
        arr[j + 1] = arr[j];//交换位置
      }
    arr[j + 1] = temp;
  }
}
}

二、进阶模板

1.快速排序    时间复杂度o()这个递归比非递归快是怎么回事????

 int partion(int a[], int left, int right)

 {

     //取最右边的元素作划分元素

     int temp = a[right];

     //记录 i = left, j = right

    int i = left, j = right-1;

     //循环直到左右指针相遇

     while(true)

      {

         //从左边开始扫描,当出现比划分元素大的元素,扫描停止

         while(temp > a[i])

          {

             i++;

         }

        //从右边进行扫描,当出现比划分元素小的元素,扫描停止

        while(temp < a[j]  && j >= left)

         {

             j--;

         }

          //如果 i >= j, 循环截止,下面的交换不执行

  • ·          if(i >= j) break;
  • ·          //交换停止时的元素
  • ·          swap(a[i], a[j]);
  • ·      }
  • ·      //交换该元素与划分元素
  • ·      swap(a[i], a[right]);
  • ·      Print(a, 0, 6);
  • ·      //printf("i = %d", i);
  • ·      //划分过程结束
  • ·      return i;
  • ·  }
  • ·  //快速排序

递归实现:

  • ·  void qsort(int a[], int left, int right)
  • ·  {
  • ·      //排序完成,循环截止
  • ·      if(right <= left)
  • ·          return;
  • ·      //做划分
  • ·      int i = partion(a, left, right);
  • ·      //对左部分排序
  • ·      if(left < (i-1))
  • ·          printf("对%d~%d排序 ", left, i-1), qsort(a, left, i-1);

    //对右部分排序

          if(right > (i+1))

         printf("对%d~%d排序 ", i+1, right), qsort(a, i+1, right);

 }

 非递归实现:
·  void qsort(int a[], int left, int right)

  • ·  {
  • ·      int i;
  • ·      //定义栈s
  • ·      stack<int> s;
  • ·      //先判断栈是否为空
  • ·      while(!s.empty())
  • ·      {
  • ·          //若栈不为空,将栈中元素移出
  • ·          s.pop();
  • ·      }
  • ·      //将right入栈
  • ·      s.push(right);
  • ·      //将left入栈
  • ·      s.push(left);
  • ·      //while循环,当栈为空时,循环结束
  • ·      while(!s.empty())
  • ·      {
  • ·          //元素left出栈
  • ·          left = s.top(), s.pop();
  • ·          //元素right出栈
  • ·          right = s.top(), s.pop();
  • ·          //判断left与right的关系,如果left>=right,continue
  • ·          if(left >= right)
  • ·          {
  • ·              continue;
  • ·          }
  • ·          //作划分
  • ·          i = partion(a, left, right);
  • ·          //比较两个子数组的大小
  • ·          //将子数组中的较大者压入栈
  • ·          if((i-1-left) > (right-i-1))
  • ·          {
  • ·              s.push(i-1);
  • ·              s.push(left);
  • ·              s.push(i+1);
  • ·              s.push(right);
  • ·          }
  • ·          else
  • ·          {
  • ·              s.push(i+1);
  • ·              s.push(right);
  • ·              s.push(i-1);
  • ·              s.push(left);
  • ·          }
  • ·      }
  • ·  }

三、例题

题目描述

输入 n(n<5000000 n为奇数) 个数字 ai(0<ai<109),输出这些数字的第 k 小的数。最小的数是第 0 小。

输入格式

输出格式

输入输出样例

输入 #1 

5 1

4 3 2 1 5

输出 #1 

2

代码:

#include<bits/stdc++.h>using namespace std;int x[5000005],k;void qsort(int l,int r){

int i=l,j=r,mid=x[(l+r)/2];

do

{

while(x[j]>mid)

j--;

while(x[i]<mid)

i++;

if(i<=j)

{

swap(x[i],x[j]);

i++;

j--;

}

}

while(i<=j);

//快排后数组被划分为三块: l<=j<=i<=r

if(k<=j) qsort(l,j);//在左区间只需要搜左区间

else if(i<=k) qsort(i,r);//在右区间只需要搜右区间

else //如果在中间区间直接输出

{

printf("%d",x[j+1]);

exit(0);

}

}int main(){

int n;

scanf("%d%d",&n,&k);

for(int i=0;i<n;i++)

scanf("%d",&x[i]);

qsort(0,n-1);

}

原文地址:https://www.cnblogs.com/wtx2333/p/13574324.html