参考慕课陈越姥姥的数据结构课程。
参考博客
使用的交换函数
void swab(int array[], int index1, int index2)
{
int tmp = array[index1];
array[index1] = array[index2];
array[index2] = tmp;
}
void printArray(int array[], int length)
{
for(int i=0; i<length; ++i)
cout<<array[i]<<" ";
cout<<endl;
}
1.冒泡排序
时间复杂度O(n^2), 每次比较相邻的两个元素,将最大的元素后移
void bubbleSort(int arr[], int length)
{
for(int i=0; i<length; ++i)
{
for(int j=0; j<length-1; ++j)
{
if(arr[j]>arr[j+1])
swab(arr, j, j+1);
}
}
}
对于可能存在部分排序好的序列,可以优化为
void bubbleSort2(int arr[], int length)
{
int flag = 0;
for(int i=0; i<length; ++i)
{
for(int j=0; j<length-1; ++j)
{
if(arr[j]>arr[j+1])
{
swab(arr, j, j+1);
flag=1;
}
}
if(!flag)
break;
}
}
2.选择排序
时间复杂度O(n^2), 数组前半部分为已排序好的,每次选出未排序数组的最小值放在已排序数组的最后。
void selectionSort(int arr[], int length)
{
for(int i=0; i<length; ++i)
{
int min_idx = i;
for(int j=i+1; j<length; ++j)
{
if(arr[j]<arr[min_idx])
{
min_idx = j;
}
}
swab(arr, i, min_idx);
}
}
3.插入排序
时间复杂度O(n^2), 数组的前半部分为已排序数组,后半部分为未排序数组,针对未排序数组,依次取出,插入在排序数组中合适的位置。和选择排序的区别:选择排序每次选出未排序数组的最小元素作为已排序数组的最大值,插入在其最后;插入排序则是从未排序数组中依次取出,然后在排序数组中寻找合适位置插入。
void insertSort(int arr[], int length)
{
for(int i=1; i<length; ++i)
{
for(int j=i-1; j>=0; --j)
{
if(arr[j+1]<arr[j])
swab(arr, j+1, j);
else
break;
}
}
}
4.希尔排序
时间复杂度O(n^3/2),在插入排序的基础上优化,采用跳跃式插入排序。
void shellSort(int arr[], int length)
{
for(int D=length/2; D>0;D/=2)
{
for(int i=D; i<length; ++i)
{
for(int j=i-D; j>=0; j-=D)
{
if(arr[j+1]<arr[j])
swab(arr, j+1, j);
else
break;
}
}
}
}
5.堆排序
时间复杂度O(nlogn),采用最大堆的方式。
void heapCore(int arr[], int length, int parent)
{
if(parent>length)
return ;
int l_node = 2*parent + 1;
int r_node = 2*parent + 2;
int maxIdx = parent;
if(l_node<length&&arr[l_node]>arr[maxIdx])
maxIdx = l_node;
if(r_node<length&&arr[r_node]>arr[maxIdx])
maxIdx = r_node;
if(maxIdx!=parent)
{
swab(arr, maxIdx, parent);
heapCore(arr, length, maxIdx);
}
}
void buildHeap(int arr[], int length)
{
for(int i=(length-1)/2; i>=0; --i)
{
heapCore(arr, length, i);
}
}
void heapSort(int arr[], int length)
{
buildHeap(arr, length);
for(int i=length-1; i>=0; --i)
{
swab(arr, i, 0);
heapCore(arr, i, 0);
}
}
6.归并排序
时间复杂度O(nlogn),分而治之的思想,递归的方法。
void merge(int arr[], int start, int end, int* res)
{
int length = end-start+1;
int lStart = start, rStart = length/2 + start;
int resStart = start;
while (lStart<=start+length/2-1&&rStart<=end)
{
if(arr[lStart]>arr[rStart])
{
res[resStart++] = arr[rStart++];
}
else
{
res[resStart++] = arr[lStart++];
}
}
while(lStart<=start+length/2-1)
res[resStart++] = arr[lStart++];
while(rStart<=end)
res[resStart++] = arr[rStart++];
for(int i=start; i<=end; ++i)
arr[i] = res[i];
}
void mergeSortCore(int arr[], int start, int end, int* res)
{
if(end==start)
return ;
mergeSortCore(arr, start, (end+start)/2, res);
mergeSortCore(arr, (end+start)/2+1, end, res);
merge(arr, start, end, res);
}
void mergeSort(int arr[], int length)
{
int* res = new int[length];
mergeSortCore(arr, 0, length-1, res);
delete [] res;
}
7.快速排序
时间复杂度O(nlogn),每次将一个元素排在正确的位置上。
int part(int arr[], int start, int end)
{
int baseIdx = start;
while (start < end)
{
while (start<end&&arr[end]>arr[baseIdx])
--end;
while (start < end&&arr[start] <= arr[baseIdx])
++start;
swab(arr, start, end);
}
swab(arr, start, baseIdx);
return start;
}
void qucikSortCore(int arr[], int start, int end)
{
if(start<end)
{
int base = part(arr, start, end);
qucikSortCore(arr, start, base-1);
qucikSortCore(arr, base+1, end);
}
}
void quickSort(int arr[], int length)
{
qucikSortCore(arr, 0, length-1);
}
8.桶排序
时间复杂度O(n),当数组的范围很大时, 需要开辟很大额外空间。适用于数组的范围比较小的时候。
void bucketSort(int arr[], int length)
{
int* tmp = new int[length+1];
memset(tmp, 0, sizeof(tmp)*(length+1));
for(int i=0; i<length; ++i)
{
++tmp[arr[i]];
}
int idx=0;
for(int i=0; i<length;++i)
{
while(tmp[i]>0)
{
arr[idx++] = i;
--tmp[i];
}
}
delete [] tmp;
}
9.基数排序
时间复杂度P(N+B), 在桶排序的基础上优化,P为排序的趟数,N为数字的个数, B为桶的个数。
基数排序分为次位优先(Least Significant Digit, LSM)和主位优先(Main Significant Digit, MSD)。适用于数组比较小,但范围比较大的时候。
int findMax(int arr[], int length)
{
int max = arr[0];
for(int i=1;i<length;++i)
if(arr[i]>max)
max=arr[i];
return max;
}
void radixSort(int arr[], int length)
{
int radix=10;
int max = findMax(arr, length);
for(int i=1; max>0; i*=10, max/=10)
{
vector<int>* bucket = new vector<int> [length];
for(int j=0;j<length;++j)
{
bucket[(arr[j]/i)%10].push_back(arr[j]);
}
int k=0;
for(int j=0; j<10; ++j)
{
for(int m=0; m<bucket[j].size(); ++m)
arr[k++] = bucket[j][m];
}
delete bucket;
}
}