首页 > 代码库 > 排序算法习题汇总

排序算法习题汇总

1.冒泡排序

对于一个int数组,请编写一个冒泡排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。 

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class BubbleSort {
public:
    int* bubbleSort(int* A, int n) {
        // write code here
        for(int i=0;i<n-1;i++){
            int k=0;
            for(int j=0;j<n-i-1;j++){
                if(A[j]>A[j+1]){
                    k=A[j];
                    A[j]=A[j+1];
                    A[j+1]=k;
                }
}
        }
        return A;
    }
};

2.选择排序

对于一个int数组,请编写一个选择排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class SelectionSort {
public:
    int* selectionSort(int* A, int n) {
        // write code here
        for(int i=0;i<n;i++){
            int min=A[i];
            for(int j=i+1;j<n;j++){
                if(A[j]<A[i]){min=A[i];A[i]=A[j];A[j]=min;}
            }
        }
        return A;
    }
};

3.插入排序

对于一个int数组,请编写一个插入排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class InsertionSort {
public:
    int* insertionSort(int* A, int n) {
        // write code here
        for(int i=1;i<n;i++) {
            int min=0;
            for(int j=i;j>0;j--){
                if(A[j]<A[j-1]){
                    min=A[j];
                    A[j]=A[j-1];
                    A[j-1]=min;
                }
            }
               
           }
        return A;
    }
};

4.归并排序

对于一个int数组,请编写一个归并排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class MergeSort {
public:
    int* mergeSort(int* A, int n) {
        // write code here
        mergeSort(A,0,n-1);
        return A;
        
    }
//划分区间
void mergeSort(int* &A,int start,int end) { if(start==end)return; int mid=(start+end)/2; mergeSort(A,start,mid); mergeSort(A,mid+1,end); Sort(A,start,mid,mid+1,end); }
//排序
void Sort(int* &A,int a,int b,int c,int d) { int i=b,j=d; int len=d-a; int k=d-a+1; int temp[k]; while(i>=a&&j>=c) { if(A[i]>A[j]) {temp[len--]=A[i--];} else{temp[len--]=A[j--];} } while(i>=a)temp[len--]=A[i--]; while(j>=c)temp[len--]=A[j--]; for(int f=0;f<k;f++) A[a+f]=temp[f]; } };

5.快速排序

对于一个int数组,请编写一个快速排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class QuickSort {
public:
    int* quickSort(int* A, int n) {
        // write code here
       Sort(A,0,n-1);
        return A;
    }
//不断的把大的往右,小的往左,小划分,嵌入递归小排
void Sort(int* &A,int start,int end) { if(start>=end)return; int i=start; int j=end; int k=A[i]; while(i<j) { while(i<j&&A[j]>k){j--;} if(i<j){A[i]=A[j];i++;} while(i<j&&A[i]<k){i++;} if(i<j){A[j]=A[i];} A[i]=k; Sort(A,start,i-1); Sort(A,i+1,end); } } };

6.堆排序

对于一个int数组,请编写一个堆排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class HeapSort {
public:

    void swap(int* A,int a,int b) {
        int temp = A[a];
        A[a] = A[b];
        A[b] = temp;
    }

public:


        void adjust_heap(int* A, int i, int n) {
        int left = 2*i+1;
        int right = 2*i+2;
        int max_id = i;
        if (i>n)return;
        if ((left<n)&&(A[left]>A[max_id]))max_id = left;
        if ((right<n)&&(A[right]>A[max_id]))max_id = right;
        if (max_id !=i) {
            swap(A, max_id,i);
            adjust_heap(A,max_id, n);
        }
    }
public:
    void build_heap(int* A,int n) {
        for (int i=(n-2)/2;i>=0;i--) {
            adjust_heap(A, i, n);
        }
    }
public:
        int* heapSort(int* A,int n) {
        // write code here
        build_heap(A, n);
        for (int i=n-1;i>0;i--) {
            swap(A, 0, i);
            adjust_heap(A,0,i);
        }
        return A;
    }
};

7.希尔排序

对于一个int数组,请编写一个希尔排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。保证元素小于等于2000。

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class ShellSort {
public:
   void swap(int* A,int a,int b){
       int temp=A[a];
       A[a]=A[b];
       A[b]=temp;
   }
    public:
    void shell_sort(int *A,int step,int n){
        for(int i=0;i<n-step;i+=step){
            for(int j=0;j<n-step;j+=step){
                if(A[j]>A[j+step])swap(A,j,j+step);
            }
        }
    }
    int* shellSort(int* A, int n) {
        // write code here
        for(int i=n-1;i>0;i--){
            shell_sort(A,i,n);
        }
        return A;
    }
};

8.计数排序

对于一个int数组,请编写一个计数排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class CountingSort {
public:
    int* countingSort(int* A, int n) {
        // write code here
        int temp[1000]={0};
        for(int i=0;i<n;i++){
            temp[A[i]]++;
        }
        int count_index=0;
        for(int j=0;j<1000;j++){
            if(temp[j]!=0){
                for(int i=0;i<temp[j];i++){
                A[count_index]=j;
                count_index++;}
            }
        }
         return A;
    }
};

9.基数排序

对于一个int数组,请编写一个基数排序算法,对数组元素排序。

给定一个int数组A及数组的大小n,请返回排序后的数组。保证元素均小于等于2000。

测试样例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
class RadixSort {
public:
    int data_dot(int data,int dot_position){
        return (int)(data/pow(10,dot_position-1))%10;
    }
    void Radix_sort(int* A,int dot_position,int n){
        int temp[10][2000]={0};
        int index=0;
        for(int i=0;i<n;i++){
           int test= data_dot(A[i],dot_position);
            temp[test][A[i]]++;
        }
        int new_index=0;
       for(int j=0;j<10;j++){
           for(int k=0;k<2000;k++){
               if(temp[j][k]!=0){
                   for(int q=0;q<temp[j][k];q++){A[new_index++]=k;}
               }
           }
       }
        
    }
    int* radixSort(int* A, int n) {
        // write code here
        for(int i=1;i<5;i++){
            Radix_sort(A,i,n);
        }
        return A;
    }
};

综合排序练习:

1.(小范围排序)

已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。

给定一个int数组A,同时给定A的大小n和题意中的k,请返回排序后的数组。

测试样例:
[2,1,4,3,6,5,8,7,10,9],10,2
返回:[1,2,3,4,5,6,7,8,9,10]
class ScaleSort {
public:
    void adjustHeap(vector<int> &B, int p, int k){
        int l = 2 * p + 1;
        int r = l + 1;
        while (l < k){
            if (r < k){ //有右孩子
                if (B[l] < B[p] && B[l] <= B[r]){
                    swap(B[p],B[l]);
                    p = l;
                }
                else if (B[r] < B[p] && B[r] <= B[l]){
                    swap(B[p], B[r]);
                    p = r;
                }
                else{
                    break;  //不用交换,堆顶已经最大了
                }
            }
            else{
                if (B[l] < B[p]){
                    swap(B[p], B[l]);
                    p = l;
                }
                else{
                    break;
                }
            }
            l = p * 2 + 1;
            r = l + 1;
        }
    }
    void buildHeap(vector<int> & B, int k){
        for (int i = k-1; i>=0; i--){
            adjustHeap(B,i, k);
        }
    }
    vector<int> sortElement(vector<int> A, int n, int k) {
        // write code here
        int sz = n - k + 1;
        vector<int> B(A.begin(), A.begin() + k);
        buildHeap(B, k);
        int i;
        for ( i = 1; i<sz; i++){
            A[i - 1] = B[0];
            B[0] = A[i+k-1];
            adjustHeap(B, 0,k);
        }
        //最后加一个k的堆排序
        i = n - k;
        for (int j=1; i < n; i++,j++){
            A[i] = B[0];
            swap(B[k-j], B[0]);
            adjustHeap(B, 0, k - j);
        }
        return A;
    }
};

2.(重复值判断)

请设计一个高效算法,判断数组中是否有重复值。必须保证额外空间复杂度为O(1)。

给定一个int数组A及它的大小n,请返回它是否有重复值。

测试样例:
[1,2,3,4,5,5,6],7
返回:true
class Checker {
public:
    
    bool checkDuplicate(vector<int> a, int n) {
        // write code here
        int temp[10000]={0};
        for(int i=0;i<n;i++){
            temp[a[i]]++;
        }
        for(int j=0;j<10000;j++){
            if(temp[j]>=2)return true;
        }
        return false;
    }
};

3.(有序数组结合)

有两个从小到大排序以后的数组A和B,其中A的末端有足够的缓冲空容纳B。请编写一个方法,将B合并入A并排序。

给定两个有序int数组AB,A中的缓冲空用0填充,同时给定A和B的真实大小int n和int m,请返回合并后的数组。

class Merge {
public:

    int* mergeAB(int* A, int* B, int n, int m) {
        // write code here
      while(m!=0){
          if(n==0){A[m-1]=B[m-1];m--;}
          else{
              if(A[n-1]>B[m-1]){A[m+n-1]=A[n-1];n--;}
              else{A[m+n-1]=B[m-1];m--;}
              
          }
      }
        return A;
    }
};

4.(三色排序)

有一个只由0,1,2三种元素构成的整数数组,请使用交换、原地排序而不是使用计数进行排序。

给定一个只含0,1,2的整数数组A及它的大小,请返回排序后的数组。保证数组大小小于等于500。

测试样例:
[0,1,1,0,2,2],6
返回:[0,0,1,1,2,2]
class ThreeColor {
public:
     void swap(vector<int>&A,int a,int b){
            int temp=A[a];
            A[a]=A[b];
            A[b]=temp;
        }
    vector<int> sortThreeColor(vector<int> A, int n) {
        // write code here
       int left=-1;int right=n;int index=0;
        while(index<right){
            if(A[index]==0){++left;swap(A,left,index);index++;}
            else if(A[index]==2){--right;swap(A,right,index);}
            else{index++;}
        }
        return A;
    }
};

5.(有序矩阵查找)

现在有一个行和列都排好序的矩阵,请设计一个高效算法,快速查找矩阵中是否含有值x。

给定一个int矩阵mat,同时给定矩阵大小nxm及待查找的数x,请返回一个bool值,代表矩阵中是否存在x。所有矩阵中数字及x均为int范围内整数。保证nm均小于等于1000。

测试样例:
[[1,2,3],[4,5,6],[7,8,9]],3,3,10
返回:false
class Finder {
public:
    bool findX(vector<vector<int> > mat, int n, int m, int x) {
        // write code here
        int i=0;
        int j=m-1;
        while(j>=0&&i<n){
            if(mat[i][j]==x)return true;
            else if(mat[i][j]>x)j--;
            else{ i++;}
        }
        return false;
    }
};

6.最短子数组

对于一个数组,请设计一个高效算法计算需要排序的最短子数组的长度。

给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的长度。(原序列位置从0开始标号,若原序列有序,返回0)。保证A中元素均为正整数。

测试样例:
[1,4,6,5,9,10],6
返回:2
class Subsequence {
public:
    int shortestSubsequence(vector<int> A, int n) {
        // write code here
        int max=A[0],min=A[n-1];
        int max_index=0,min_index=n-1;
        for(int i=1;i<n;i++)
        {
            if(A[i]>=max)
            {
                max=A[i];
            }
            else
            {
                max_index=i;
            }
        }
        for(int j=n-2;j>0;j--)
        {
            if(A[j]<=min)
            {
                min=A[j];
            }
            else
            {
                min_index=j;
            }
        }
        if(min_index > max_index) {
           if(min_index-max_index+1 == n) return 0;
           else 
               return min_index-max_index+1;
       }
        else {
            return max_index-min_index+1;
        }
    }
};

7.相邻俩数字最大差值

有一个整形数组A,请设计一个复杂度为O(n)的算法,算出排序后相邻两数的最大差值。

给定一个int数组AA的大小n,请返回最大的差值。保证数组元素多于1个。

测试样例:
[1,2,5,4,6],5
返回:2
class Gap {
public:
    int maxGap(vector<int> A, int n);
};
 
int Gap::maxGap(vector<int> A, int n)
{
    if (n < 2)
        return 0;
    set<int> iset;
    for (const auto &i : A)
        iset.insert(i);
    auto pre = iset.begin();
    int max = 0;
    for (auto iter = ++iset.begin();iter != iset.end();++iter)
    {
        if (*iter - *pre > max)
            max = *iter - *pre;
        ++pre;
    }
    return max;
}

乱入扩展题

 技术分享

#include<iostream>
#include<vector>
using namespace std;
void print_array(vector<vector<int> >&test, int index,int array_size);
int main(){
    cout << "请输入数组的维度:" << endl;
    int N;
    cin >> N;
    int k = 0;
    vector<vector<int> >test(N, vector<int>(N));
    
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
             test[i][j]=k++;
        }
    }
    cout << "结果输出:" << endl;
    for (int test_i = 0; test_i < int((N+1)/2); test_i++) {
        print_array(test,test_i,N);
    }
    cin.get();
    cin.get();
}
void print_array(vector<vector<int> >&a, int index,int array_size) {
    for (int i = index; i <=array_size - 1 - index; i++) {
        cout << a[index][i]<<endl;
    }
    for (int j = index+1; j <=array_size - index - 1; j++) {
        cout << a[j][array_size - index - 1] << endl;;
    }
    for (int m = array_size - index - 2;m >= index; m--) {
        cout << a[array_size - index - 1][m]<<endl;
    }
    for (int n = array_size - index - 2; n >index; n--) {
        cout << a[n][index]<<endl;
    }
}

 

排序算法习题汇总