排序(2)
四. 二路归并排序(非递归形式):
时间复杂度: O(n*log(n))
空间复杂度: O(n)
稳定性: 稳定
static void Merge(int ar[], int len, int gap) // gap 几几合并 { int* br = (int*)malloc(sizeof(int) * len); assert(br != NULL); int low1 = 0; int high1 = low1 + gap - 1; int low2 = high1 + 1; int high2 = (low2 + gap - 1) < len ? (low2 + gap - 1) : len-1; int index = 0; while (low2 < len)//两个有序段 { while (low1 <= high1 && low2 <= high2)//两个都没走到尾 { if (ar[low1] <= ar[low2]) { br[index++] = ar[low1++]; } else { br[index++] = ar[low2++]; } } while (low2 <= high2) //有一个走到尾,则将另一个剩余的数据拷贝到br中 { br[index++] = ar[low2++]; } while (low1 <= high1) { br[index++] = ar[low1++]; } low1 = high2 + 1;//更改low1 ,low2指向下一对有序段 high1 = low1 + gap - 1; low2 = high1 + 1; high2 = (low2 + gap - 1) < len ? (low2 + gap - 1) : len - 1; } while (low1 < len)//只有一个有序段 { br[index++] = ar[low1++]; } //拷贝到ar中 for (int i = 0; i < len; i++) { ar[i] = br[i]; } free(br); br = NULL; return; } void MergeSort(int ar[], int len) { assert(ar != NULL && len > 1); for (int i = 1; i < len; i *= 2) { Merge(ar, len, i); } }
五.(简单)选择排序 :
规则:每次从待排序的队列中找到最小的元素,与待排序的第一个元素交换
效率: 时间复杂度O(n^2)
空间复杂度O(1)
稳定性: 不稳定
void SelectSort(int ar[], int len) { assert(ar != NULL && len > 1); for (int i = 0; i < len - 1; i++) { //int min = ar[i]; int index = i; int j = i + 1; for (; j < len; j++) { if (ar[j] < ar[index]) { //min = ar[j]; index = j; } } if (index != i) { int tmp = ar[index]; ar[index] = ar[i]; ar[i] = tmp; } } }
六 堆排序:
效率: 时间复杂度 O(n*log(2,n))
空间复杂度: O(1)
稳定性: 不稳定
//简单介绍下堆: //什么是堆: 堆分为两种 大顶堆(一个二叉树,父节点的值大于子节点的值) 小顶堆 // 什么是树形结构 //二叉树 树根 深度(log 2(节点个数)+1) 叶子节点(没有子结点的结点) 左孩子 右孩子 完全二叉树() 满二叉树() // // 大顶堆和小顶堆的关系和兄弟节点的值无关,只和父子节点的值有关 // // 调整2个要点 1.从最后一个非叶子结点开始从后向前调整 // 2.调整时从上向下 // 3.升序(大顶堆),降序(小顶堆) // //父子结点关系: //父 x 找 子 y1,y2 : 左y1 = 2*x + 1, 右y2 = 2*x + 2; //子 y1,y2 找 父 x : x = (y1/y2 - 1)/2; void HeapAdjust(int ar[], int start, int end)//传入开始的结点和结束的结点下标 { int tmp = ar[start]; for (int i = start * 2 + 1; i <= end; i = 2*i+1) { if (i < end && ar[i] < ar[i+1])//两个孩子都有且左孩子大于右孩子 { i++;//让i指向较大的孩子 } //只有一个孩子不进行比较 if (ar[i] > tmp) { ar[start] = ar[i]; start = i; } else { break; } } ar[start] = tmp;//1.触底2.找到合适位置 } void HeapSort(int ar[], int len) { assert(ar != NULL && len > 1); //1.调整成大顶堆 for (int i = (len-1)/2; i >= 0; i--) { HeapAdjust(ar, i, len - 1); } int tmp = 0; for (int j = 0; j < len - 1; j++)//4. 循环1,2,3操作 { //2.将根结点(最大值)和最后一个结点交换,并继续调整 tmp = ar[0]; ar[0] = ar[len - 1 - j]; ar[len - 1 - j] = tmp; //3.将剩下的继续进行调整 HeapAdjust(ar, 0, len - 1 - j - 1); } }
未完待续...