赞
踩
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的 大 小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有 序序列。
-
- void InsertSort(int* a, int n) {
- //[0,end]的区间有序 把end+1的数向前插入
- for (int i = 0; i < n - 1; i++) {
- int end = i;
- int tmp = a[end + 1];
- while (end >= 0)
- {
- if (tmp < a[end])
- {
- a[end + 1] = a[end];
- end--;
- }
- else {
- break;
- }
- }
- a[end + 1] = tmp;
- }
- }
-
-
希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
- void ShellSort(int* a, int n) {
- //希尔分为预排序和插入排序,预排序是分组写
- int gap = n;
- while (gap > 1)
- {
- gap = gap / 3 + 1;
- for (int i = 0; i < n - gap; i++)
- {
- int end = i;
- 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;
- }
- }
- }
在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素。
这里的代码是对选择排序的优化版本,它可以同时选出最大值和最小值。
- //选择排序
- void SelectSort(int* a, int n) {
- //遍历选出最小的和最大的数的下标,再进行交换最小的换到最左边,最大的换到最右边
- int begin = 0,end=n-1;
-
- while (begin < end)
- {
- int min = begin, max = begin;//每次循环后缩小区间
- for (int i = begin + 1; i <= end; i++)
- {
- if (a[i] < a[min])
- {
- min = i;
- }
- if (a[i] > a[max])
- {
- max = i;
- }
- }
- //swap(&a[begin], &a[min]);
- 防止最大的下标和开始一样,最小的和end一样,导致重复两次置换数组元素
- //if (max == begin)
- //{
- // max = min;
- //}
- //swap(&a[end], &a[max]);
- swap(&a[end], &a[max]);
- if (min == end)
- {
- min = max;
- }
- swap(&a[begin], &a[min]);
- begin++;
- end--;
- }
- Print(a, n);
- }
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
- //堆排序
-
- void AdjustDown(HPDataType* a, int parent,int n) {
-
- int child = parent * 2 + 1;
- while (child<n)
- {
- //选出左右孩子里小的那个,child+1要小于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) {
- //升序建大堆,降序建小堆
- int i = 0;
- for (i = (n - 1 - 1) / 2; i >= 0; i--)
- {
- AdjustDown(a, i, n);
- }
- int end = n - 1;//end记录最后一个节点的下标,把第一个节点和最后一个节点换位置然后向下调整
- while (end>0)
- {
- swap(&a[0], &a[end]);
- AdjustDown(a, 0, end);
- end--;
- }
- }
冒泡排序是在数组中对相邻两个元素进行对比,依次循环知道所有数据有序。属于最简单的排序算法之一。
- //冒泡排序
- void BubbleSort(int* a, int n) {
- for (int j = 0; j < n; j++)
- {
- for (int i = 0; i < n-j-1; i++)
- {
- if (a[i] > a[i + 1])
- {
- swap(&a[i], &a[i + 1]);
- }
- }
- }
- Print(a, n);
- }
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
- //经典快排
- void PartSort1(int* a, int left, int right) {
- int begin, end;
- begin = left, end = right;
- if (left >= right)
- return;//返回条件
- int keyi = left;
- while (left < right)
- {
- while(left<right&&a[right] >= a[keyi])//R找小,R必须先走,必须要有left<right的判断条件要不right和left相遇无法判断
- {
- right--;
- }
- while(left<right&&a[left] <= a[keyi])//L找大
- {
- left++;
- }
- swap(&a[left], &a[right]);
- }
- swap(&a[left], &a[keyi]);
- keyi = left;
- // [begin,keyi]keyi[keyi+1,end]
- PartSort1(a, begin, keyi);
- PartSort1(a, keyi + 1, end);
- }
- void PartSort3(int* a, int left, int right) {
- int prev = left,cur=left+1;
- if (left >= right)
- return;
- int keyi = left;
- while (cur < right +1)
- {
- if (a[cur]<a[keyi])
- {
- prev++;
- swap(&a[prev], &a[cur]);
- }
- cur++;
- }
- swap(&a[prev], &a[keyi]);
- keyi = prev;
- //[left,keyi]
- PartSort3(a, left, keyi);
- PartSort3(a, keyi+1, right);
- }
借用数据结构栈来进行堆递归时栈帧的模拟,每一次把区间的端点值入到栈中,先入右端点再入左端点,出栈的时候先出左端点再出右端点。之后再以keyi为界限把区间再度二分。依次循环直到栈为空。
- void QuickSortNonR(int* a, int left, int right) {
- //栈中存放区间端点,先入右端点后入左端点。
- Stack st;
- StackInit(&st);
- StackPush(&st, right);
- StackPush(&st, left);
- while (!StackEmpty(&st))
- {
- int begin=StackTop(&st);
- StackPop(&st);
- int end = StackTop(&st);
- StackPop(&st);
- int cur = begin + 1, prev = begin, keyi = begin;
- while (cur <=end)
- {
- if (a[cur] < a[keyi])
- {
- prev++;
- swap(&a[prev], &a[cur]);
- }
- cur++;
- }
- swap(&a[prev], &a[keyi]);
- keyi = prev;
- //[begin,keyi]keyi[keyi+1,end]
- if (keyi + 1 < end)
- {
- StackPush(&st, end);
- StackPush(&st, keyi + 1);
- }
- if (keyi > begin)
- {
- StackPush(&st, keyi);
- StackPush(&st, begin);
- }
- }
-
- StackDestroy(&st);
- }
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
- void _MergeSort(int* a, int begin, int end, int* tmp)
- {
- if (begin == end)
- return;
-
- int mid = (begin + end) / 2;
- // [begin, mid] [mid+1, end]
- _MergeSort(a, begin, mid, tmp);
- _MergeSort(a, mid+1, end, tmp);
-
- // 归并
- int begin1 = begin,end1 = mid;
- int begin2 = mid + 1,end2 = end;
- int i = begin;
- // 依次比较,取小的尾插tmp数组
- 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++];
- }
-
- memcpy(a+begin, tmp + begin, sizeof(int) * (end - begin + 1));
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。