赞
踩
排序算法是一种将一组数据按照特定顺序排列的算法。数据结构排序算法的选择取决于数据的特征、规模和性能需求。
接下来我们就要实现排序~~
我们需要实现的一些功能:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<stdbool.h> #include<time.h> // 打印 void Print_a(int* a, int sz); // 交换 void Swap(int* p1, int* p2); // 插入排序 void InsertSort(int* a, int n); // 冒泡排序 void BubbleSort(int* a, int n); // 希尔排序 void ShellSort(int* a, int n); // 堆排序 void AdjustDwon(int* a, int n, int root); void HeapSort(int* a, int n); // 选择排序 void SelectSort(int* a, int n); // ------------------------------------------------------ // 快速排序hoare版本 int PartSort1(int* a, int begin, int end); // 快速排序挖坑法 int PartSort2(int* a, int begin, int end); // 快速排序前后指针法 int PartSort3(int* a, int begin, int end); // 排序函数 void QuickSort(int* a, int begin, int end); //------------------------------------------------------ // 快速排序 非递归实现 void QuickSortNonR(int* a, int begin, int end); // 归并排序递归实现 void MergeSort(int* a, int n); // 归并排序非递归实现 void MergeSortNonR(int* a, int n); // 非比较排序 void CountSort(int* a, int n);
代码实现:
void bubbleSort(int* a,int n)
{
for (int i = 0; i < n-1; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
if (a[j] > a[j + 1])
{
Swap(&a[j], &a[j + 1]);
}
}
}
}
优点:
缺点:
代码实现:
void InsertSort(int* a, int n) { for (int i = 0; i < n - 1; i++) { // 记录每次i的位置 int end = i; // 将i+1的位置保存 int tmp = a[end + 1]; // 一次排序 while (end >= 0) { // 如果后面的数字小于前面的那一个就进行往后覆盖, // 然后end--,继续排序 if (tmp < a[end]) { a[end + 1] = a[end]; --end; } else { // 如果大于或者等于了就跳出 break; } } // 因为--end了,所以就要在end+1的位置放刚刚保存的值tmp a[end + 1] = tmp; } }
优点:
缺点:
代码实现:
void ShellSort(int* a, int n) { int gap = n; // gap > 1时是预排序,目的让他接近有序 // gap == 1是直接插入排序,目的是让他有序 while (gap > 1) { // gap = gap / 2; // log 2 N gap = gap / 3 + 1; // log 3 N //每次排gap次 for (int j = 0; j < n - gap; j++) { //插入排序 int end = j; int tmp = a[end + gap]; while (end >= 0) { if (tmp < a[end]) { a[end + gap] = a[end]; end -= gap; } else { break; } } a[end + gap] = tmp; } } }
优点:
缺点:
代码实现:
// 选择排序 void SelectSort(int* a, int n) { int begin = 0, end = n - 1; while (begin < end) { // 两头找 int mini = begin, maxi = begin; for (int i = begin + 1; i <= end; i++) { // 如果i的位置比mini小就更新一下 if (a[i] < a[mini]) { mini = i; } //如果i的位置比maxi大就更新一下 if (a[i] > a[maxi]) { maxi = i; } } // 走到这里就说明小的要和左边交换一下 Swap(&a[mini], &a[begin]); // 注意:这里Eugene左边的和maxi相等了要更新一下maxi if (begin == maxi) { maxi = mini; } // 然后交换maxi和end Swap(&a[end], &a[maxi]); ++begin; --end; } }
优点:
缺点:
堆排序是一种基于二叉堆数据结构的排序算法。它利用了堆的性质来进行排序,其中堆分为最大堆和最小堆两种类型。在最大堆中,父节点的值大于或等于其子节点的值;在最小堆中,父节点的值小于或等于其子节点的值。
这里在堆排序章节已经讲过了,这里就不细讲了~~
代码实现:
void AdjustDwon(int* a, int n, int root) { int parent = root; int child = parent * 2 + 1; while (child < n) { if (child + 1 < n && a[child + 1] > a[child]) ++child; if (a[child] > a[parent]) { Swap(&a[child], &a[parent]); parent = child; child = parent * 2 + 1; } else { break; } } } void HeapSort(int* a, int n) { for (int i = (n - 1 - 1) / 2; i >= 0; i--) { AdjustDwon(a, n, i); } int end = n - 1; while (end > 0) { Swap(&a[0], &a[end]); AdjustDwon(a, end, 0); --end; } }
优点:
缺点:
int GetMidi(int* a, int left, int right) { //int midi = (begin + end) / 2; int mid = (left + right) >> 1; if (a[left] < a[mid]) { if (a[mid] < a[right]) return mid; else if (a[left] > a[right]) return left; else return right; } else // a[left] > a[mid] { if (a[mid] > a[right]) return mid; else if (a[left] < a[right]) return left; else return right; } }
代码实现:
int PartSort1(int* a, int begin, int end) { // 三数取中 int midi = GetMidi(a, begin, end); Swap(&a[midi], &a[begin]); // 要在最左边开始 int left = begin, right = end; int keyi = begin; while (left < right) { // 右边找小 while (left < right && a[right] >= a[keyi]) { --right; } // 左边找大 while (left < right && a[left] <= a[keyi]) { ++left; } // 找到了,就交换 Swap(&a[left], &a[right]); } // 交换的左边的和keyi,然后更新一下keyi Swap(&a[left], &a[keyi]); return left; } void QuickSort(int* a, int begin, int end) { if (begin >= end) return; // 小区间 if (end - begin + 1 < 10) { InsertSort(a + begin, end - begin + 1); } else { int keyi = PartSort1(a, begin, end); QuickSort(a, begin, keyi - 1); QuickSort(a, keyi + 1, end); } }
优点:
缺点:
代码实现:
int PartSort2(int* a, int begin, int end) { int midi = GetMidi(a, begin, end); Swap(&a[midi], &a[begin]); int key = a[begin]; int holei = begin; while (begin < end) { // 右边找小 while (begin < end && a[end] >= key) { --end; } a[holei] = a[end]; holei = end; // 左边找大 while (begin < end && a[begin] <= key) { ++begin; } a[holei] = a[begin]; holei = begin; } a[holei] = key; return holei; } void QuickSort(int* a, int begin, int end) { if (begin >= end) return; // 小区间 if (end - begin + 1 < 10) { InsertSort(a + begin, end - begin + 1); } else { int keyi = PartSort2(a, begin, end); QuickSort(a, begin, keyi - 1); QuickSort(a, keyi + 1, end); } }
优点:
缺点:
代码实现:
int PartSort3(int* a, int begin, int end) { int midi = GetMidi(a, begin, end); Swap(&a[begin], &a[midi]); int prev = begin; int cur = prev + 1; int keyi = begin; while (cur <= end) { if (a[cur] < a[keyi] && ++prev != cur) Swap(&a[prev], &a[cur]); ++cur; } Swap(&a[keyi], &a[prev]); keyi = prev; return prev; } void QuickSort(int* a, int begin, int end) { if (begin >= end) return; // 小区间 if (end - begin + 1 < 10) { InsertSort(a + begin, end - begin + 1); } else { int keyi = PartSort3(a, begin, end); QuickSort(a, begin, keyi - 1); QuickSort(a, keyi + 1, end); } }
优点:
缺点:
代码实现:
#include"Stack.h" // 快速排序 非递归实现 void QuickSortNonR(int* a, int begin, int end) { ST s; StackInit(&s); // 先入右后入左 StackPush(&s, end); StackPush(&s, begin); while (!StackEmpty(&s)) { // 先出左后出右 int left = StackTop(&s); StackPop(&s); int right = StackTop(&s); StackPop(&s); // 排序 int keyi = PartSort3(a, left, right); // [left keyi-1] keyi [keyi+1 right] if (left < keyi - 1) { StackPush(&s, keyi - 1); StackPush(&s, left); } if (keyi + 1 < right) { StackPush(&s, right); StackPush(&s, keyi + 1); } } StackDestroy(&s); }
代码实现:
void _MergeSort(int* a, int begin, int end, int* tmp) { if (begin >= end) return; // 分割 // 这里右移一位相当于 /2 int mid = (begin + end) >> 1; // 递归 _MergeSort(a, begin, mid, tmp); _MergeSort(a, mid + 1, end, tmp); // [begin mid][mid+1 end] 归并 int begin1 = begin, end1 = mid; int begin2 = mid + 1, end2 = end; int i = begin; while (begin1 <= end1 && begin2 <= end2) { if (a[begin1] <= a[begin2]) { tmp[i++] = a[begin1++]; } else { tmp[i++] = a[begin2++]; } } while (begin1 <= end1) { tmp[i++] = a[begin1++]; } while (begin2 <= end2) { tmp[i++] = a[begin2++]; } // 拷贝回原数组 for (int i = begin; i <= end; ++i) { a[i] = tmp[i]; } //memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin) + 1); } // 归并排序递归实现 void MergeSort(int* a, int n) { int* tmp = (int*)malloc(sizeof(int) * n); if (tmp == NULL) { perror("malloc fail!\n"); return; } _MergeSort(a, 0, n - 1, tmp); free(tmp); }
优点:
缺点:
代码实现:
void MergeSortNonR(int* a, int n) { int* tmp = (int*)malloc(sizeof(int) * n); int gap = 1; // 每组数据个数 while (gap < n) { for (int i = 0; i < n; i += 2 * gap) { // [i, i+gap-1] [i+gap,i+2*gap-1] int begin1 = i, end1 = i + gap - 1; int begin2 = i + gap, end2 = i + 2 * gap - 1; // 归并过程中右半区间可能就不存在 if (begin2 >= n) break; // 归并过程中右半区间算多了, 修正一下 if (end2 >= n) { end2 = n - 1; } int index = i; while (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++]; } // 拷贝回去 for (int j = i; j <= end2; ++j) { a[j] = tmp[j]; } } gap *= 2; } free(tmp); }
代码实现:
void CountSort(int* a, int n) { int max = a[0], min = a[0]; for (int i = 0; i < n; i++) { if (a[i] > max) max = a[i]; if (a[i] < min) min = a[i]; } int range = max - min + 1; int* count = (int*)malloc(sizeof(int) * range); if (count == NULL) { perror("malloc fail!\n"); return; } memset(count, 0, sizeof(int) * range); //统计次数 for (int i = 0; i < n; i++) { count[a[i] - min]++; } int i = 0; for (int j = 0; j < range; j++) { while (count[j]--) { a[i++] = j + min; } } free(count); }
优点:
缺点:
代码实现:
这里就先不实现,之后会开一个新文章来进行阐述,并且使用C++
来写~~
优点:
缺点:
本期内容就到这里了,感谢大家的收看,欢迎三连~~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。