// 冒泡排序
void bubbleSort(vector& array) {
for (size_t i = 0; i < array.size(); i++) {
// 当前轮是否发生过交换事件标志位,若未发生交换,则表明列表已有序。
bool isExchanged = false;
for (size_t j = 0; j < array.size() - i - 1; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
isExchanged = true;
}
}
if (!isExchanged){
break;
}
}
}
// 选择排序
void selectSort(vector& array){
for (size_t i = 0; i < array.size(); i++){
size_t minIndex = i;
for (size_t j = i + 1; j < array.size(); j++){
if (array[minIndex] > array[j]){
minIndex = j;
}
}
if (minIndex != i){
swap(array[i], array[minIndex]);
}
}
}
// 插入排序
void insertionSort(vector& array){
// i 代表无序序列首元素(无序序列前为有序序列)
size_t i = 1;
while (i < array.size()){
size_t j = i - 1;
int itermToInsert = array[i];
while (j >= 0){
if (array[j] >= itermToInsert){
array[j + 1] = array[j];
j--;
}
else{
break;
}
}
array[j + 1] = itermToInsert;
i++;
}
}
// 希尔排序
void shellSort(vector& array){
int n = array.size();
for (int gap = n / 2; gap >= 1; gap /= 2){
for (int i = gap; i < n; i++){
// 使用插入排序算法,将元素依次插入所在小组的已排序列表中
// 待插入元素
int itermToInsert = array[i];
int j = i - gap;
while (j >= 0 && array[j] >= itermToInsert){
array[j + gap] = array[j];
j -= gap;
}
array[j + gap] = itermToInsert;
}
}
}
递归实现
// 归并排序
// 合并两有序序列,两序列分别为array的0到mid部分和mid+1到末尾部分。
void merge(vector& array, vector& copyArray, int left, int right) {
int mid = (left + right) / 2;
int i = left, j = mid + 1, k = 0;
while (i <= mid || j <= right) {
if (i > mid) {
copyArray[k] = array[j];
j++;
}
else if (j > right) {
copyArray[k] = array[i];
i++;
}
else if (array[i] > array[j]) {
copyArray[k] = array[j];
j++;
}
else {
copyArray[k] = array[i];
i++;
}
k++;
}
for (size_t i = left; i <= right; i++) {
array[i] = copyArray[i - left];
}
}
void mergeSortHelp(vector& array, vector& copyArray, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSortHelp(array, copyArray, left, mid);
mergeSortHelp(array, copyArray, mid + 1, right);
merge(array, copyArray, left, right);
}
}
// 归并排序 递归实现
void mergeSort(vector& array) {
vector copyArray(array);
mergeSortHelp(array, copyArray, 0, array.size() - 1);
}
迭代实现
// 归并排序 迭代实现
void mergeSortIteration(vector& array) {
vector copyArray(array);
int left = 0, right = array.size() - 1;
stack> boundaries;
while (left < right || !boundaries.empty()) {
if (left < right) {
boundaries.push({ left, right });
right = (left + right) / 2;
}
else {
vector boundary = boundaries.top();
boundaries.pop();
left = boundary[0];
right = boundary[1];
merge(array, copyArray, left, right);
if (boundaries.empty()) {
break;
}
boundary = boundaries.top();
left = right + 1;
right = boundary[1];
}
}
}
递归版:
// 快速排序(递归)
// 选则最左端、最右端和中间位置3元素的中值作为基准值,并将3元素排序,返回基准值
int medianPovit(vector& array, int left, int mid, int right){
if (array[left] > array[mid]){
swap(array[mid], array[left]);
}
if (array[left] > array[right]){
swap(array[left], array[right]);
}
if (array[mid] > array[right]){
swap(array[mid], array[right]);
}
return array[mid];
}
// 分区,返回基准索引
int partition(vector& array, int left, int right) {
// 中间位置索引
int mid = (left + right) / 2;
// 基准值(此时基准值对应索引为mid)
int povit = medianPovit(array, left, mid, right);
// 将基准值与倒数第二个元素交换
array[mid] = array[right - 1];
array[right - 1] = povit;
int i = left, j = right - 1;
while (i < j) {
if (array[i] < povit) {
i++;
}
else if (array[j] >= povit) {
j--;
}
else {
swap(array[i], array[j]);
}
}
// 交换基准值和i位置元素
swap(array[i], array[right - 1]);
return i;
}
void quickSortHelp(vector& array, int left, int right) {
if (left < right) {
int pivotLoction = partition(array, left, right);
quickSortHelp(array, left, pivotLoction - 1);
quickSortHelp(array, pivotLoction + 1, right);
}
}
// 快速排序
void quickSort(vector& array) {
quickSortHelp(array, 0, array.size() - 1);
}
迭代版:
// 快速排序 非递归(迭代版)
void quickSortIteration(vector& array) {
stack> boundaries;
int left = 0, right = array.size() - 1;
while (left < right || !boundaries.empty()) {
if (left >= right) {
vector boundary = boundaries.top();
boundaries.pop();
left = boundary[0];
right = boundary[1];
}
int pivotLoction = partition(array, left, right);
if (pivotLoction + 1 < right) {
boundaries.push({ pivotLoction + 1, right });
}
right = pivotLoction - 1;
}
}
将数字转化为一个堆;
堆是具有以下两属性的二叉树:
(1)每个节点的值大于等于其子节点的值;
(2)树完全平衡,即最底层叶子节点都位于左侧(完全),且左右子树高度相差不超过1(平衡);
因为,堆是完全平衡树,因此可以用数组直接表示:
堆也被称为优先队列,具有先进先出的特性,在堆底插入元素,在堆顶取出元素。
取出堆顶元素(最大元素),作为有序数数组末尾元素,并对二叉树进行调整使其满足堆的特性;
重复上一步骤,依次取出堆顶元素,并插入到有序数组中,上一插入元素之前的位置,直到堆空为止;
// 堆排序
// 调整堆,根元素沿树向下移动,直至其合适位置,first和last分别为堆顶和堆底在数组array中的索引
void moveDown(vector& array, int first, int last){
// first的左子节点索引
int curIndex = first * 2 + 1;
while (curIndex <= last){
// 若first有2子节点,令curIndex为其值最大子节点索引
if (curIndex < last && array[curIndex] < array[curIndex + 1]){
curIndex++;
}
// 若根节点值小于子节点值,则交换
if (array[first] < array[curIndex]){
swap(array[first], array[curIndex]);
first = curIndex;
curIndex = first * 2 + 1;
}
else{
break;
}
}
}
// 用数组实现堆
void buildHeap(vector& array){
// 最后一个非叶节点的节点索引
int i = array.size() / 2 - 1;
while (i >= 0){
moveDown(array, i, array.size() - 1);
i--;
}
}
// 堆排序
void heapSort(vector& array){
// 生成堆
buildHeap(array);
// 堆顶、底索引
int first = 0, last = array.size() - 1;
while (first <= last){
swap(array[first], array[last]);
last--;
moveDown(array, first, last);
}
}
// 计数排序
void countSort(vector& array){
if (array.empty()){
return;
}
//找出最大最小值
int min = array.front(),max = array.front();
for (int i = 1; i < array.size(); i++){
if (min > array[i]){
min = array[i];
}
else if (max < array[i]){
max = array[i];
}
}
// 记录各元素出现次数
vector counts(max - min + 1);
for (int i = 0; i < array.size(); i++){
counts[array[i] - min]++;
}
// 根据记录的次数输出对应元素
int index = 0;
for (int j = 0; j < counts.size(); j++){
int n = counts[j];
while (n--){
array[index] = j + min;
index++;
}
}
}
// 桶排序
void bucketSort (vector& array, int bucketCount){
if (array.empty()){
return;
}
// 找出最大最小值
int max = array.front(), min = array.front();
for (int i = 1; i < array.size(); i++){
if (min > array[i]){
min = array[i];
}
else if (max < array[i]){
max = array[i];
}
}
// 将待排序的各元素分入对应桶中
vector> buckets(bucketCount);
int bucketSize = ceil((double)(max - min + 1) / bucketCount);
for (int i = 0; i < array.size(); i++){
int bucketIndex = (array[i] - min) / bucketSize;
buckets[bucketIndex].push_back(array[i]);
}
// 对各桶中元素进行选择排序
int index = 0;
for (vector bucket : buckets){
if (!bucket.empty()){
// 使用选择排序算法对桶内元素进行排序
selectSort(bucket);
for (int value : bucket){
array[index] = value;
index++;
}
}
}
}
// 桶排序
void bucketSort (vector& array){
bucketSort (array, array.size() / 2);
}
// 基数排序 (只适用于正数,此处不适用)
void radixSort(vector& array){
// 当前位数
int curdigit = 10;
// 当前位是否已超过最高为
bool isOverHighest = false;
while (!isOverHighest){
isOverHighest = true;
// 利用分桶的思想来实现按各位进行排序
vector> buckets(10);
for (int curVal : array){
int bucketIndex = curVal % curdigit - curVal % (curdigit / 10);
buckets[bucketIndex].push_back(curVal);
if (isOverHighest && curVal / curdigit){
isOverHighest = false;
}
}
// 按照桶的顺序,将各桶内元素拼接起来
int index = 0;
for (vector bucket : buckets){
for (int value : bucket){
array[index] = value;
index++;
}
}
curdigit *= 10;
}
}
从高位开始排序,可以有更少的交换次数,因为高位较大的数,值必然更大;
(1)根据最高位,对数据进行排序,对于高位数值唯一的元素,此时所处的位置即为其最终位置;
(2)对当前位数值相等的多个元素,根据更低一位进行排序;
(3)重复第2步,直至当前待排序区段内当前位排序后各数值唯一或当前位为最低位。
// 基数排序,对array的left到right区段,按照curDigit位进行排序 void radixSortImproveHelp(vector
& array, int left, int right, int curDigit) { if (left >= right || curDigit < 10) { return; } // 将各元素按当前位数值大小分入各桶 vector > buckets(10); for (int i = left; i <= right; i++) { int bucketIndex = (array[i] % curDigit - array[i] % (curDigit / 10)) / (curDigit / 10); buckets[bucketIndex].push_back(array[i]); } // 按照桶的顺序,将桶中元素拼接 // 对于元素个数大于1的桶,桶内元素按照更低位来进行排序 int index = 0; for (vector bucket : buckets) { int newLeft = index, newRight = index; for (int value : bucket) { array[index] = value; index++; } newRight = index - 1; radixSortImproveHelp(array, newLeft, newRight, curDigit / 10); } } // 基数排序(从高位开始) void radixSortImprove(vector & array) { // 计算当前数组最大数位数 int curDigit = 10; for (int value : array) { if (value / curDigit) { curDigit *= 10; } } radixSortImproveHelp(array, 0, array.size() - 1, curDigit); }