龙空技术网

排序算法详细汇总对比分析(C++)

暖橙Yoka 262

前言:

此时兄弟们对“数组下标能为负数吗”大体比较关心,看官们都需要知道一些“数组下标能为负数吗”的相关内容。那么小编同时在网络上汇集了一些对于“数组下标能为负数吗””的相关内容,希望咱们能喜欢,咱们一起来了解一下吧!

第一种最常用的就是

## 1.选择排序:

时间复杂度:O(N*N)

大致思想为:从第一个数开始,依次从后面所有数中挑出最小的那个数(包括比较第一个数),然后与第一个数进行数值交换。

自己写代码总会出现或多或少的小问题:

注意:

(1)swap函数记得加上头文件#include<algorithm>

(2)自己写交换函数记的用引用传递,int temp = a;a=b;

b=temp;这个交换顺序自己在纸上写一写。

(3)为了可以容纳多种类型数组,加入模板T,同时包装成一个函数,这样float型数组(小数),string型数组(字符串)都可以进行排序。

```cpp

#include<iostream>

using namespace std;

#include<algorithm>

//void swap(int& a, int& b)

//{

// int temp = a;

// a=b;

// b=temp;

//}

template<typename T>

void selectSort(T arr[], int n){

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

{

int min = i;

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

{

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

min = j;

}

swap(arr[i],arr[min]);

}

}

int main(){

int n=6;

int arr[6]={5,2,4,3,6,1};

selectSort(arr,6);

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

{

//cout<<"排序后:"<<endl;

cout<<arr[k]<<" ";

}

while(1);

return 0;

}

```

后来专门搞了一个随机生成数组值得函数,放在SorttestHelper.h文件里,代码如下。

**这里学习到的一个点是它的返回类型是namespace,根据这个代码可知,该返回类型是一个指向新开辟的数组空间的指针。,但事实上它返回的数组空间,只是用指针表示一下。为什么这么说呢,int * arr = 该函数, 也就是用一个指针指向该函数返回的数组空间!注意在最后用delete[] arr; 释放一下那个函数开辟的数组空间。**

```cpp

#include<iostream>

#include<ctime>

#include<cassert>

using namespace std;

namespace SortTestHelper {

// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]

int *generateRandomArray(int n, int range_l, int range_r) {

int *arr = new int[n];

srand(time(NULL));

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

arr[i] = rand() % (range_r - range_l + 1) + range_l;

return arr;

}

```

## 2.插入排序:

时间复杂度:O(N*N)

选择排序的思想是从该数后面找到最小与该数进行交换,而插入排序的思想是,从第二个开始,把该数放到前面所有数的数组中对应的位置。(**一个是把后面整体看成数组,一个是把前面整体看成一个数组)**

```cpp

template<typename T>

void InsertSort(T arr[], int n){

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

for(int j=i;j>0; j--){

if(arr[j]<arr[j-1])//!这里是关键,j和j-1比较!

swap(arr[j],arr[j-1]);

else

break;

}

}

}

```

再补充一个比较:这个插入排序是j和j-1进行比较,而选择排序是j和保存的最小值进行比较!

注意:**插入排序如果第一轮该数比前面的数组的第一个比较的数大,那么后面就不用再继续了。所以相对选择排序来说应该是更快一点!但是事实上,是可能快也可能慢,因为有时候插入排序相比选择排序需要交换更多次!所以下面出现了插入排序的优化!**

**但是插入排序最大的优点在于,对于接近有序的序列,插入排序可以实现效率非常的高,甚至比很多时间复杂度小的排序方法都高,而现实生活中很多事物的排序都属于接近有序的排序,比如不小心被打乱的时间,或者注册表等!所以其实用价值很高!可以降到o(n)的复杂度。**

## 插入排序优化:

观察下面的程序,改进后的方法:就是减少交换,把交换都换成了赋值。怎么个赋值法?

**把当前的数保存在一个临时变量中(对应T e = arr[i];),然后将前面的数组和临时变量比,要是临时变量小(或者说该数小),暂时先不和之前一样让他们交换,而是就把较大的数赋值给后面的小数,一直到前面数组中哪个数比该数小,好,跳出来,把该数放在数组中这个数后面!**

```cpp

template<typename T>

void InsertSort(T arr[], int n){

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

T e = arr[i];

int j;

for( j=i;j>0 && e <arr[j-1]; j--){

arr[j]=arr[j-1];

}

arr[j] = e;

}

}

```

**最后再强调一下:**

**插入排序最大的优点在于,对于接近有序的序列,插入排序可以实现效率非常的高,甚至比很多时间复杂度小的排序方法都高,而现实生活中很多事物的排序都属于接近有序的排序,比如不小心被打乱的时间,或者注册表等!所以其实用价值很高!**

## 3.希尔排序(难)

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

自我感觉写入排序的原理很好理解,就是把序列分组之后再进行插入排序,没有看过的可以看看这篇[希尔排序]()

难就难在代码的分析上:

下面是相对插入排序几个改动的地方,我依次解释:

```cpp

template<typename T>

void Shell_sort(T arr[], int n){

for(int gap = n/2; gap>0; gap/=2)//改动

{

//改动i=gap

for(int i =gap; i<n; i++){

T e = arr[i];

int j;

//改动j>gap,j<gap时就结束

//改动e <arr[j-gap]

//改动j-=gap

//改动j-=gap

for( j=i;j-gap>=0 && e <arr[j-gap]; j-=gap){

arr[j]=arr[j-gap];

}

arr[j] = e;

}

}

}

```

第一个改动就是加入了gap循环,这个gap既代表有几个分组,又代表分组后每个元素之间的间隔。它循环起来是因为希尔排序要进行多次分组,每次分组都不同。直到gap=0就不用分了,这时候就排好了。

第二次改动把插入排序的初始值换了,以前是从第2个数开始作为要插入的对象,往前面的数组插入,现在是先把第gap个数作为插入对象,**这个gap在它现在的分组中其实就是第2个数!**

第三个改动j-gap>=0,它就相当于之前插入排序的j-1>=0,这个不用理解,只要知道数组下标不能为负数,所以j-1≥0,所以j-gap>=0。

另外两个比较简单就不说了就不用说了。

注意:**分组之后的排序是交错排序,不是先把其中一组排完再排另一组!!!是按照顺序交错排序!**

## 4.冒泡排序

时间复杂度:O(N*N)

这个比较简单,就从第一个开始,与它相邻的比较,要是偏大就交换,这样一直交换下去,最后面的那个就得到了最大值。第一轮交换最后面那个值排好,第二轮倒数后两个值排好,既然每次倒着数都增加一个排好的值,那就每一轮减少一个值的排序,只用排序前n-i个。

```cpp

template<typename T>

void maopao_sort(T arr[], int n){

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

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

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

swap(arr[j],arr[j+1]);

}

}

}

```

**当然,其实你for(int j=0;j<n-1-i; j++)这里不需要-i也是可以的。每一轮把一个数冒到最后面去,需要n-1轮就把全部都冒到后面去了!所以叫冒泡排序!**

## 5.归并排序(中等难度)

归并排序就稍微麻烦一点,但是它的时间复杂度是nlogn,通过增大空间复杂度减少了时间复杂度,所以也应用广泛。

它的基本原理就是利用递归,先对数组二分法进行分组,分组之后对各个小组分别进行归并排序,然后分好的各个小组再分组,再各自进行归并排序,最后对整体进行一次归并排序。

它的代码如下,分为三个部分,第一部分换个名字,第二部分实现递归,第三部分实现最后的合并。其中第三部分最为复杂。

```cpp

//归并排序

template<typename T>

void merge(T arr[], int n){

//先给函数换个参数传递

_merge_sort(arr, 0, n-1);

}

template<typename T>

void _merge_sort(T arr[], int L,int R){

//利用递归方法,先找结束条件

if(L>=R)return;

//先把数组分成两份

int mid = (L+R)/2;//R-L

//再分别对分成的两组进行归并排序

_merge_sort(arr, L, mid);

_merge_sort(arr,mid+1,R);

//最后对整体进行归并排序

_merge(arr, L,mid,R);

}

template<typename T>

void _merge(T arr[],int L,int mid,int R){

T* aux = new T [R-L+1];//建立临时数组

//T aux[R-L+1];

//把原数组的值赋值到临时数组

//并且新数组的下标是从0开始的

for(int i= L; i<=R; i++){

aux[i-L] = arr[i];

}

//下面就是归并排序的核心思想了

int i =L;

int j =mid+1;

for(int k=L;k<=R;k++){

//是i>mid,不是>j

//前两个if是一端遍历完了,一端还没有

//后面两个是在借用临时数组把最小的按顺序保存到原数组中

//记得所有的aux里都要减去L

if(i>mid){

arr[k]=aux[j-L];

j++;//!不要忘记!

}else if(j>R)

{

arr[k]=aux[i-L];

i++;//!!

//下面这里注意,下面两个不能单独if出来,必须和上面一起

//因为当一端越界的时候,不能再执行下面的if判断,i越界还好,j越界就超出数组范围了

}else if(aux[i-L]<aux[j-L]){

arr[k]=aux[i-L];

i++;

}else{

arr[k]=aux[j-L];

j++;

}

}

delete[] aux;

}

```

## 对归并排序的优化

把第二个函数修改一下,改了两个地方:

第一个大于的时候在合并,不大于就不用了。

1.if(arr[mid]>arr[mid+1])//不大于的时候其实已经排好了

_merge(arr, L,mid,R);

2.改变结束条件,数组比较小的时候用插入排序就好!

```cpp

template<typename T>

void _merge_sort(T arr[], int L,int R){

//利用递归方法,先找结束条件

//if(L>=R)return;

if(R-L<=15){

InsertSort_merge(arr,L,R);

return;

}

//先把数组分成两份

int mid = (L+R)/2;//R-L

//再分别对分成的两组进行归并排序

_merge_sort(arr, L, mid);

_merge_sort(arr,mid+1,R);

//最后对整体进行归并排序

if(arr[mid]>arr[mid+1])//不大于的时候其实已经排好了

_merge(arr, L,mid,R);

}

```

## 自底向上的归并排序(难)

(这个比较难懂,初学者看不懂就放弃吧)

1.划分小段,划到最小,对各个小段分别进行归并排序

2.划分小段(相比上面的小段,各个小段更长),分别进行归并排序

3.一直到最后,对整个数组进行归并排序

整个过程不需要递归,只需要迭代就可以

```cpp

//自底向上的归并排序

template<typename T>

void mergeBU(T arr[], int n){

//第一层遍历是每次分组后的单组的元素个数

for(int sz=1; sz<=n; sz+=sz){

//每两个组进行一次归并排序处理

//i+sz<n保证了第二组的存在

//min()函数是为了不存在第二部分末尾的时候,就把末尾换成数组末尾

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

_merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1));

}

}

}

```

优点:这种排序没有使用数组的一个特性,就是通过数组下标直接获得元素,时间复杂度是nlogn的时间,因此,可以非常好的对链表进行排序。

## 6.快速排序(最伟大的排序!)

快速排序的核心思想这个帖子讲的非常好:[快速排序]()

这里有句话

> 首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动,这一点非常重要(请自己想一想为什么)

**搞清楚了,首先搞清一个原则,最后与基准数的交换,一定是与一个小于基准数的数交换!但是链接错误的地方在于,它的结束条件是两边指针汇合处,但汇合处可能大于0,也可能小于0,所以结束条件必须是左边指针大于右边指针,然后最后交换只能是和j交换,因为j暂停的时候指向是小于基准数的数,i大于j的时候,j指向也一定是小于基准数的数,这样最后交换才会成立。所以不论哪个指针先动都可以,只要改变结束条件就行!后面有我参考修正后的代码!**

上面是双路指针的快速排序,我先贴出快速排序的最原始的版本:

它的原理比较复杂,用的也不多,这里就不展开讲解,大致说下:

如下图,两个指针j,i; i进行遍历,当遇到小于基准数的值时,把它和j+1进行交换,即大于基准数组部分的第一个;当遇到大于基准数组的值时,不用动。最后把基准数和j(也就是小于基准数组部分的最后一个数)进行交换即可。

![在这里插入图片描述]()

```cpp

//快速排序原始形态

template<typename T>

void quick_sort(T arr[], int n){

//先换个名字

__quicksort(arr,0,n-1);

}

template<typename T>

void __quicksort(T arr[],int L,int R){

//结束条件

//if(L>=R)return;

//优化方案

if(R-L<=15){

InsertSort_merge(arr,L,R);

return;

}

//接下来找到中间值

int p = __patition(arr,L,R);

//对两边分别再用快速排序

__quicksort(arr,L,p);

__quicksort(arr,p+1,R);

}

template<typename T>

int __patition(T arr[], int L, int R){

//优化方案

srand((unsigned int)time(NULL));

swap(arr[L],arr[rand()%(R-L+1)+L]);

//创建一个临时基准数

T v = arr[L];

//arr[L+1,....j]<v ; arr[j+1....i]>v

int j=L;

for(int i=L+1;i<=R;i++){

if(arr[i]<v){

swap(arr[i],arr[j+1]);

j++;

}

}

swap(arr[L],arr[j]);

return j;

}

```

**原始快速排序的最大缺点是:针对特别有序的数组,排序起来可能特别慢!为什么呢?快速排序每次都是分为两部分,一边大于基准数,一边小于基准数,然后再对两边分别进行递归,但是当遇到几乎完全有序的数组时,分出来的就是,一边全是大于基准数的,一边什么都没有,这时候就要对另一边几乎剩余全部进行递归,依次下去,时间复杂度就退化回了O(n*n)了。这种情况的改进方法就是基准数不要从头开始,每次都随机选择一个!(优化方法如上!)**

**另外,针对重复数量比较多的数组,原始快速排序也会特别慢!上面原始排序如果遇到等于基准数是不动的,直接包含到大于基准数部分。跟上面的情况类似,如果全部都是等于基准数的值,那么几乎所有的数都被分到大于等于基准数那一部分,造成两部分严重失衡,最后退回到O(n*n)时间复杂度。针对这种情况,下面改进后 的双路快速排序改进了这种缺点。**

## 双路快速排序法(简单)

这种双路快速排序就是上面链接里的方法。**和原始快速排序相比,这次把大于小于基准数的部分放到了两边,i在中间移动。当两边指针都卡在等于v的元素上,就让他们交换位置。所以等于v的元素最终保留在两部分内,相比上面只保留在一部分要好很多!**

![在这里插入图片描述]()

![在这里插入图片描述]()

```cpp

template<typename T>

int __patition2(T arr[], int L, int R){

srand((unsigned int)time(NULL));

swap(arr[L],arr[rand()%(R-L+1)+L]);

//创建一个临时基准数

T v = arr[L];

//arr[L+1,....j]<v ; arr[j+1....i]>v

int i=L+1,j=R;

while(true){

//这里必须是i先循环,否则就会程序崩溃!!

//循环结束就停在了左侧第一个大于基准数的地方

while(arr[i]<v && i<=R)i++;

//循环结束## 标题就停在了右侧第一个小于基准数的地方

//!j>=L+1,否则程序崩溃!

while(arr[j]>v && j>=L+1)j--;

//如果指针重合并越界了

if(i>j)break;

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

i++;

j--;

}

swap(arr[L],arr[j]);

return j;

}

```

## 三路快速排序(针对多个重复值把排序时间压缩到最短)

**针对多个重复值把排序时间压缩到最短,因为这种方法针对等于基准数的值就不用管,不用像前两个方法一样还要划分到两部分内。同时针对重复并不是很多的情况排序时间也不会太长,基本上稍弱于双路快速排序!**

如图所示,三路排序用三个指针lt,gt,i,划定了三个范围。多了一个等于v的范围。**它的方法和不再是前后两端指针找到后交换,而是如果i找到小于基准数的值,就把它和lt+1交换,把它放到小于基准数组部分的下一个,如果i遍历的值大于基准数,就把放到gt-1,大于基准数组部分的前一个。然后等于的都让他放中间。**

![在这里插入图片描述]()

```cpp

//三路快速排序(最高效的排序)

template<typename T>

void quick3_sort(T arr[], int n){

srand((unsigned int)time(NULL));

//先换个名字

__quicksort(arr,0,n-1);

}

template<typename T>

void __quicksort3(T arr[],int L,int R){

//结束条件

//if(L>=R)return;

if(R-L<=15){

InsertSort_merge(arr,L,R);

return;

}

//随机选择一个临时基准数

swap(arr[L],arr[rand()%(R-L+1)+L]);

T v = arr[L];

//分成三部分,arr[L+1...lt]<v; arr[lt+1...i-1]=v; arr[gt...R]>v

//注意三个指针的起始位置

int lt=L;

int gt=R+1;

int i=L+1;

while(i<gt){

if(arr[i]<v){

swap(arr[i],arr[lt+1]);

lt++;

i++;

}else if(arr[i]>v){

swap(arr[i],arr[gt-1]);

gt--;

}else{

i++;

}

}

swap(arr[L],arr[lt]);

//对两边分别再用快速排序

__quicksort3(arr,L,lt-1);

__quicksort3(arr,gt,R);

}

```

## 汇总

```cpp

#include<iostream>

using namespace std;

#include<algorithm>

#include<ctime>

//void swap(int& a, int& b)

//{

// int temp = a;

// a=b;

// b=temp;

//}

//选择排序

template<typename T>

void selectSort(T arr[], int n){

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

{

int min = i;

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

{

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

min = j;

}

swap(arr[i],arr[min]);

}

}

/*----------------------------------------------------------*/

//原始插入排序

template<typename T>

void InsertSort1(T arr[], int n){

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

for(int j=i;j>=1; j--){

if(arr[j]<arr[j-1])//!这里是关键,j和j-1比较!

swap(arr[j],arr[j-1]);

else

break;

}

}

}

//改进后的插入排序

template<typename T>

void InsertSort2(T arr[], int n){

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

T e = arr[i];

int j;

for( j=i;j>=1 && e <arr[j-1]; j--){

arr[j]=arr[j-1];

}

arr[j] = e;

}

}

/*----------------------------------------------------------*/

//希尔排序

template<typename T>

void Shell_sort(T arr[], int n){

for(int gap = n/2; gap>0; gap/=2)

{

for(int i =gap; i<n; i++){

T e = arr[i];

int j;

for( j=i;j-gap>=0 && e <arr[j-gap]; j-=gap){

arr[j]=arr[j-gap];

}

arr[j] = e;

}

}

}

/*----------------------------------------------------------*/

//冒泡排序

template<typename T>

void maopao_sort(T arr[], int n){

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

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

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

swap(arr[j],arr[j+1]);

}

}

}

/*----------------------------------------------------------*/

//归并排序

template<typename T>

void merge(T arr[], int n){

//先给函数换个参数传递

_merge_sort(arr, 0, n-1);

}

template<typename T>

void _merge_sort(T arr[], int L,int R){

//利用递归方法,先找结束条件

//if(L>=R)return;

if(R-L<=15){

InsertSort_merge(arr,L,R);

return;

}

//先把数组分成两份

int mid = (L+R)/2;//R-L

//再分别对分成的两组进行归并排序

_merge_sort(arr, L, mid);

_merge_sort(arr,mid+1,R);

//最后对整体进行归并排序

if(arr[mid]>arr[mid+1])//不大于的时候其实已经排好了

_merge(arr, L,mid,R);

}

template<typename T>

void _merge(T arr[],int L,int mid,int R){

T* aux = new T [R-L+1];//建立临时数组

//T aux[R-L+1];

//把原数组的值赋值到临时数组

//并且新数组的下标是从0开始的

for(int i= L; i<=R; i++){

aux[i-L] = arr[i];

}

int i =L;

int j =mid+1;

for(int k=L;k<=R;k++){

//是i>mid,不是>j

if(i>mid){

arr[k]=aux[j-L];

j++;//!不要忘记!

}else if(j>R)

{

arr[k]=aux[i-L];

i++;//!!

}else if(aux[i-L]<aux[j-L]){

arr[k]=aux[i-L];

i++;

}else{

arr[k]=aux[j-L];

j++;

}

}

delete[] aux;

}

//改进后的适用于归并的插入排序

template<typename T>

void InsertSort_merge(T arr[], int L,int R){

for(int i =L+1; i<=R; i++){

T e = arr[i];

int j;

for(j=i;j>L && e <arr[j-1]; j--){

arr[j]=arr[j-1];

}

arr[j] = e;

}

}

/*----------------------------------------------------------*/

//自底向上的归并排序

template<typename T>

void mergeBU(T arr[], int n){

//第一层遍历是每次分组后的单组的元素个数

for(int sz=1; sz<=n; sz+=sz){

//每两个组进行一次归并排序处理

//i+sz<n保证了第二组的存在

//min()函数是为了不存在第二部分末尾的时候,就把末尾换成数组末尾

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

_merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1));

}

}

}

/*----------------------------------------------------------*/

//快速排序原始形态

template<typename T>

void quick_sort(T arr[], int n){

srand((unsigned int)time(NULL));

//先换个名字

__quicksort(arr,0,n-1);

}

template<typename T>

void __quicksort(T arr[],int L,int R){

//结束条件

if(L>=R)return;

//srand((unsigned int)time(NULL));

//接下来找到中间值,下面有两种方法可选择!

int p = __patition2(arr,L,R);

//对两边分别再用快速排序

__quicksort(arr,L,p);

__quicksort(arr,p+1,R);

}

template<typename T>

int __patition(T arr[], int L, int R){

srand((unsigned int)time(NULL));

swap(arr[L],arr[rand()%(R-L+1)+L]);

//创建一个临时基准数

T v = arr[L];

//arr[L+1,....j]<v ; arr[j+1....i]>v

int j=L;

for(int i=L+1;i<=R;i++){

if(arr[i]<v){

swap(arr[i],arr[j+1]);

j++;

}

}

swap(arr[L],arr[j]);

return j;

}

template<typename T>

int __patition2(T arr[], int L, int R){

swap(arr[L],arr[rand()%(R-L+1)+L]);

//创建一个临时基准数

T v = arr[L];

//arr[L+1,....j]<v ; arr[j+1....i]>v

int i=L+1,j=R;

while(true){

//while(arr[j]>v && j>=L)j--;

//这里必须是i先循环,否则就会程序崩溃!

//循环结束就停在了左侧第一个大于基准数的地方

while(arr[i]<v && i<=R)i++;

//循环结束就停在了右侧第一个小于基准数的地方

//!j>=L+1,否则程序崩溃!

while(arr[j]>v && j>=L+1)j--;

//如果指针重合并越界了

if(i>j)break;

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

i++;

j--;

}

swap(arr[L],arr[j]);

return j;

}

/*----------------------------------------------------------*/

//三路快速排序(最高效的排序)

template<typename T>

void quick3_sort(T arr[], int n){

srand((unsigned int)time(NULL));

//先换个名字

__quicksort(arr,0,n-1);

}

template<typename T>

void __quicksort3(T arr[],int L,int R){

//结束条件

//if(L>=R)return;

if(R-L<=15){

InsertSort_merge(arr,L,R);

return;

}

//随机选择一个临时基准数

swap(arr[L],arr[rand()%(R-L+1)+L]);

T v = arr[L];

//分成三部分,arr[L+1...lt]<v; arr[lt+1...i-1]=v; arr[gt...R]>v

int lt=L;

int gt=R+1;

int i=L+1;

while(i<gt){

if(arr[i]<v){

swap(arr[i],arr[lt+1]);

lt++;

i++;

}else if(arr[i]>v){

swap(arr[i],arr[gt-1]);

gt--;

}else{

i++;

}

}

swap(arr[L],arr[lt]);

//对两边分别再用快速排序

__quicksort3(arr,L,lt-1);

__quicksort3(arr,gt,R);

}

int main(){

int n=7;

int arr[7]={10,2,0,3,9,1,7};

quick3_sort(arr,n);

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

{

//cout<<"排序后:"<<endl;

cout<<arr[k]<<" ";

}

while(1);

return 0;

}

```

标签: #数组下标能为负数吗