void ShellSort(int* arr, int n) { int gap = n; while (gap>1) { //每次对gap折半操作 gap = gap / 2; //单趟排序 for (int i = 0; i < n - gap; ++i) { int end = i; int tem = arr[end + gap]; while (end >= 0) { if (tem < arr[end]) { arr[end + gap] = arr[end]; end -= gap; } else { break; } } arr[end + gap] = tem; } } }
void swap(int* a, int* b){ //交换函数 int temp; temp = *b; *b = *a; *a = temp; };
// 下标为i的节点的父节点下标:(i-1)/2 // 下标为i的节点的左孩子下标:i*2+1 // 下标为i的节点的右孩子下标:i*2+2 void Heapify(int arr[], int n, int i) { //维护堆的性质 arr:存储堆的数组 n:数组长度 i:待维护节点的下标 int largest = i; int lson = i * 2 + 1; int rson = i * 2 + 2; if (lson < n && arr[largest] < arr[lson]) //子节点下标不能超出n,如果存在子节点大于父节点,就把最大子节点下标赋给largest largest = lson; if (rson < n && arr[largest] < arr[rson]) largest = rson; if (largest != i) { swap(&arr[largest], &arr[i]); //交换子节点和父节点 Heapify(arr, n, largest); //递归维护子节点 }
}
void Heapsort(int arr[], int n) { int i; //建堆 for (i = ((n - 1) - 1) / 2; i >= 0; i--) { Heapify(arr, n, i); } for (i = n - 1; i > 0; i--) { swap(&arr[i], &arr[0]); //将排好序的放到数组最后面 Heapify(arr, i, 0); //维护堆顶 } };
归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。代价是需要额外的内存空间。若将两个有序表合并成一个有序表,称为2-路归并。 该算法时间复杂度为O(n log n)。
// 合并 void merge(int arr[], int temparr[], int left, int mid, int right) { //标记左半区第一个未排序的元素 int l_pos = left; //标记右半区第一个未排序的元素 int r_pos = mid + 1; //临时数组下标 int pos = left;
// 合并 while (l_pos <= mid && r_pos <= right){ if (arr[l_pos] <= arr[r_pos]) //左半区第一个剩余元素更小 temparr[pos++] = arr[l_pos++]; else //右半区第一个剩余元素更小 temparr[pos++] = arr[r_pos++]; } // 合并左半区剩余的元素 while (l_pos <= mid) temparr[pos++] = arr[l_pos++]; while (r_pos <= right) temparr[pos++] = arr[r_pos++];
//把临时数组中合并后的元素复制回原来的数组 while (left <= right) { arr[left] = temparr[left]; left++; } } // 归并排序 void msort(int arr[], int temparr[], int left, int right) { //如果只有一个元素,那么就不需要划分 //只有一个元素的区域,本身就是有序的,只需要被归并即可 if (left < right) { //找中间点 int mid = (left + right) / 2; //递归划分左半区 msort(arr, temparr, left, mid); //递归划分右半区 msort(arr, temparr, mid + 1, right); //合并已经排好序的部分 merge(arr, temparr, left, mid, right); } }
void Countsort(int* arr, int n) { //找到序列中的最大值和最小值 int max = arr[0]; int min = arr[0]; for (int i = 0; i < n; i++) { if (arr[i] > max) { max = arr[i]; } if (arr[i] < min) { min = arr[i]; } }
int range = max - min + 1;//开辟空间的数量 int* countArr = (int*)malloc(sizeof(int) * range);//开辟空间 //初始化数组全部为0 memset(countArr, 0, sizeof(int) * range); //开始计数 for (int i = 0; i < n; i++) { countArr[arr[i] - min]++; }
//开始排序 int j = 0; for (int i = 0; i < range; i++) { while (countArr[i]--) { arr[j] = i + min; j++; } } free(countArr); }
/*将数字分配到各自的桶中, 然后按照桶的顺序输出排序结果*/ void sort2(int *a, int n, int loop) { int *buckets[10] = {NULL}; int c[10] = {0}; int d[10] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; int i, j, k; int row; int temp = d[loop-1];