5种常见排序方法深度剖析

来源:互联网 发布:怪物猎人捏脸数据 编辑:程序博客网 时间:2024/06/06 04:30

(一)直接插入排序

直接插入排序的思想是从下下标为1的数开始每遍历一个数,就往前比较直到插入合适的位置下面画图说明

# include<iostream>

# include<cassert>
using namespace std;
size_t *InsertSort1(size_t *array, size_t size)//直接插入排序双循环写法
{
assert(array);
for (int i = 1; i < size; i++)
{
size_t temp = array[i];
int j = i - 1;
for (; j >= 0 && temp<array[j]; j--)//查找合适的插入位置
{

array[j + 1] = array[j];//往后挪动
}
array[j+1] = temp;//找到合适的插入位置
}
return array;
}
size_t* InsertSort2(size_t *array, size_t size)//直接插入排序while循环写法
{
assert(array);
for (size_t i = 1; i < size; i++)
{
size_t index = i;
size_t temp = array[index];
size_t end = index - 1;
while (end>0 && temp < array[end])
{
array[end + 1] = array[end];
end--;
}


array[end+1] = temp;
}
return array;

}

//(二)希尔排序

size_t *ShellSort(size_t *array, size_t size)//希尔排序
{
assert(array);
int gap = size;
while (gap > 1)
{
gap = gap / 3 + 1;//定义一个间距
for (int i = 0; i < size; i++)//将gap换成1就是直接排序的部分
{
int index = i;
int temp = array[index];
int end = index - gap;
while (end>0 && temp < array[end])
{
array[end + gap] = array[end];
end -= gap;
}
array[end + gap] = temp;
}
}
return array;
}
void Print(size_t *array, size_t size)
{
for (size_t i = 0; i < size; i++)
{
cout << array[i] << " ";
}
cout << endl;

}

(三)堆排序

void AdjustDown(size_t *array, size_t size, int root)//向下调整堆
{
assert(array);
int parent = root;
int child = root * 2 + 1;
while (child < size)
{
if (child + 1 < size&&array[child] < array[child + 1])//这里要建大堆,使堆顶元素成为最大值
{
child++;
}
if (array[child]>array[parent])
{
swap(array[child], array[parent]);
parent = child;
child = child * 2 + 1;
}
else
{
break;
}
}


}

//

size_t *HeapSort(size_t*array, size_t size)//堆排序
{
assert(array);
for (int i = (size - 2) / 2; i >= 0; --i)//对所给的完全二叉树建一个大顶堆
{
AdjustDown(array, size, i);
}
for (int i = size - 1; i > 0; --i)//每次将堆顶元素和最后一个元素交换,缩小size的范围
{
swap(array[0], array[i]);    //然后从a[0]开始向下调整即可,这样又能将最大的元素调整到a[0]
AdjustDown(array, i, 0);     //的位置,如此反复便将所有的元素升序排列
}
return array;

}

(四)冒泡排序

size_t *BubleSort(size_t*array, size_t size)//冒泡排序
{
assert(array);
for(int i = 0; i < size; i++)
{
for (int j = size - 1; j > i; j--)//注意边界条件
{
if (array[j] < array[j - 1])
{
swap(array[j], array[j - 1]);
}
}
}
return array;
}
size_t * SelectionSort(size_t *array, size_t size)//选择排序从,后面的无序区依次选出最小的数和
{
assert(array);                                 //前面[0 size)分别交换用一个min记录最小的下标。
for (int i = 0; i < size-1; i++)
{
int min = i;
for (int j = i+1; j<size; j++)
{
if (array[min] > array[j])
{
min = j;
}
}
swap(array[i],array[min]);
}
return array;
}
int main()
{
size_t array[10] = { 98, 5, 2, 78, 12, 21, 55, 12, 15, 1 };
size_t size = 10;
/*size_t *p1=InsertSort1(array, 10);
Print(p1, 10);
size_t *p2=InsertSort2(array, 10);
Print(p2, 10);
size_t *p3 = ShellSort(array, 10);
Print(p3, 10);
size_t *p4 = HeapSort(array, 10);
Print(p4, 10);*/
//size_t *p5 = BubleSort(array, 10);
//Print(p5, 10);
//size_t *p6 = SelectionSort(array, 10);
//Print(p6, 10);

}

(五)快速排序和归并排序

# include<iostream># include<cassert># include<stack>using namespace std;int  ThreeGetKey(int *a, int left, int right)//三数取中法的优化key{int mid = left + (right - left) / 2;if (a[left] < a[right]){if (a[mid] < a[left]){return a[left];}else if (a[mid] < a[right]){return a[mid];}else{return a[right];}}else{if (a[mid] < a[right]){return a[right];}else if (a[mid] < a[left]){return a[mid];}else{return a[left];}}}int PartionSort1(int *a, int left, int right)//快速排序部分排序版本1{int begin = left;int end = right;int key = ThreeGetKey(a, left, right);//优化后,不优化为a[right];while (begin < end){while (a[begin]<= key&&begin < end)//这两个while循环的先后顺序一定不能交换{++begin;}while (a[end] >= key&&begin < end){end--;}if (begin < end){swap(a[begin], a[end]);}}if (a[begin]>key){swap(a[begin], a[right]);return begin;}else{return right;}}int PartionSort2(int *a, int left, int right)//快速排序部分排序版本2{int key = a[right];int cur = left;int prev = left - 1;while (cur < right){if (a[cur] < key && ++prev != cur)//cur一直向后走,只要这个值比key小               //(说明前面prev所指的值都是比key大的值)prev就向后走一步,   //若prev和cur不相等就交换{swap(a[cur], a[prev]);}cur++;}swap(a[++prev], a[right]);return prev;}void QuckSort2(int *a, int left, int right)//快速排序的非递归方法{if (left < right){stack<int> s;s.push(right);s.push(left);while(!s.empty()){int _left = s.top();s.pop();int _right = s.top();int boundary = PartionSort1(a, _left, _right);s.pop();if (_left < boundary - 1){s.push(boundary - 1);s.push(_left);}if (boundary + 1 < _right){s.push(_right);s.push(boundary + 1);}}}else{return;}}void QuckSort(int *a,int left,int right)//快速排序{if (left < right){int boundary = PartionSort1(a, left, right);//调用了优化后的部分排序QuckSort(a, left, boundary-1);//这里一定要是boundary-1,否则会出现死循环QuckSort(a, boundary + 1, right);}}void MergeSection(int *a, int*tmp, int begin1, int end1, int begin2, int end2){int index = begin1;//这不能是0while (begin1 <= end1&&begin2 <= end2){if(a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <=end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}}void _MergeSort(int *a,int *tmp ,int left, int right){if (left < right){int boundary = left + (right - left) / 2;_MergeSort(a, tmp, left, boundary);_MergeSort(a, tmp, boundary + 1, right);MergeSection(a, tmp, left, boundary, boundary + 1, right);memcpy(a + left, tmp + left, (right - left + 1)*sizeof(int));//right-left+1}}void MergeSort(int *a, int size)//归并排序{int left = 0;int right = size - 1;int* tmp = new int[size];_MergeSort(a,tmp, left, right);delete[] tmp;}void Print(int *a,int size){for (int i = 0; i <= size; i++){cout << a[i] << " ";}cout << endl; }void CountSort(int *a, size_t size)//计数排序,思想是将对应元素作为辅助矩阵的下标,在辅助矩阵中计算它的个数{assert(a);             //然后再将它拷回原来的矩阵中去int Max = a[0];int Min = a[0];for (size_t i = 1; i < size; ++i){if (a[i]>Max){Max = a[i];}else if (a[i] < Min){Min = a[i];}}int range = Max - Min + 1;int *CountArray = new int[range];memset(CountArray, 0, sizeof(int)*range);for (size_t i = 0; i < size; i++){CountArray[a[i] - Min]++;//有一个相对的偏移量,这样最小值将存在0的位置}size_t index = 0;for (size_t i = 0; i < range; ++i){while (CountArray[i]-->0){a[index++] = Min + i;}}delete[] CountArray;}int GetMaxDigit(int *a, size_t size){int digit = 1;//默认值为一位int Max = 10;for (size_t i = 0; i < size; i++){while (a[i] >= Max){++digit;Max *= 10;}}return digit;}void DigitSortLSD(int *a, size_t size){assert(a);int MaxDigit = GetMaxDigit(a, size);int *bucket = new int[size];int count[10];int start[10];int digit = 1;int bit = 1; while (digit <= MaxDigit){memset(count, 0, sizeof(int)* 10);memset(start, 0, sizeof(int)* 10);for (size_t i = 0; i < size; ++i)//统计0-9号桶有多少数字{int num = (a[i]) % 10;count[num]++;}start[0] = 0;for (size_t i = 0; i < size; ++i){start[i] = start[i - 1] + count[i - 1];//当前桶的起始位置为前一个桶的起始位置//加上前一个桶的计数个数;}for (size_t i = 0; i < size; ++i){int num = (a[i] / bit) % 10;bucket[start[num]] = a[i];}memcpy(a, bucket, sizeof(int)* 10);bit = bit * 10;++digit;}}int main(){int  a[10] = { 1, 45, 23, 21, 48, 34, 33, 23, 40, 30 };Print(a, 9);//QuckSort2(a, 0, 9);//MergeSort(a, 10);//CountSort(a, 10);DigitSortLSD(a, 10);Print(a, 9);}


1 0
原创粉丝点击