排序算法

来源:互联网 发布:vue.js是用来干嘛的 编辑:程序博客网 时间:2024/05/15 04:37

排序算法的稳定性:

如有13, 2, 44, 56, 56*, 98, 10这个序列,

 稳定排序后:2, 10, 13, 44, 56, 56*, 98, 这可以做到两个相等的元素(复杂类型中为KEY)一定不互换

但不稳定排序后的结果可能是:2, 10, 13, 44, 56*, 56, 98, 这样并不能一定保证相等的两个元素的位置不互换,\

在基本类型中稳定或不稳定是无关紧要的,

但是在复杂类型中, 根据关键字排序, 使用不稳定排序, 可能会让两个相同关键字的元素交换位置, 这可能并不是开发者所设想的



冒泡排序:

void BubleSort(int arr[], int len){//冒泡排序, 最古老的排序, 效率最低的排序    //思想 : 通过比较相临的元素, 如果前一个元素大于后一个元素, 就交换它们    //这样每次就把当前比较中的元素, 最大的元素放到最后, 达到排序的目的for (int i = 0; i < len - 1; i++){//外层循环次数为数组长度-1for (int j = 0; j < len - 1 - i; j++){//内层循环每次递减, 因为最大的元素始终在最后, 没必要在比较最大的元素if (arr[j] > arr[j + 1]){//如果前一个比较大,则交换相临的两个元素int temp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = temp;}}}}


冒泡排序进阶版->快速排序

void QuickSort(int arr[], int left/*最左边元素下标*/, int right/*最右边元素下标*/){//快速排序//思想 : 采用分治算法, 找到一个关键字, 把小于关键字的元素放在关键字的左边//把大于关键字的放在关键字的右边,然后,递归,把左边的再次使用快排,右边的也//使用快排,最后完成排序if (left >= right){//左下标和右下标重叠时, 返回return;}int i = left; //i从左往右表示下标int j = right + 1; //j从右往从表示下标, ***注 : 这里j要超尾,  j超尾, 但是right必需是最右边元素的下标***int varKey = arr[left]; //最左边的元素设定为关键字while (true){//外层循环, 把关键字放到正确位置后, 退出循环do {i++;} while (arr[i] < varKey);//从左往右找, 当找到比关键字小的, 退出do {j--;} while (arr[j] > varKey); //从右往左找, 当找到比关键字, 退出if (i >= j) {//当i与j重叠时,退出外层循环break;}//相换两个元素int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}arr[left] = arr[j];arr[j] = varKey; //最后把关键字放到左组和右组的中间, 同时也以经确定了关键字的正确位置QuickSort(arr, left, j - 1); //把关键字左边的组进行快排QuickSort(arr, j + 1, right); //所关键字右边的组进行快排}



直接插入排序

void InsertionSort(int arr[], int len){//直接插入排序//思想 : 首先让外层的当前元素为待排序元素(temp), //然后和有序列表中以从后往前的顺序进行比较//最后将待排序元素插入到以经排好序的列表中//一开始有序列表长度为1, 然后为2....直到最后长度为整个数组的长度for (int i = 1; i < len; i++){//外层循环为数组长度, 这里从第二个元素开始插入, 因为一个元素不存在排序int temp = arr[i]; //设置待排序元素int j = i - 1; while (j >= 0 && arr[j] > temp){//当j>0时, 并且待排元素小于当前比较元素, 则将当前元素后移, 然后继续同有序列表中前面的元素比较arr[j + 1] = arr[j];j--;}arr[j + 1] = temp;}}


 直接插入排序进阶版->二分插入排序

void BinInsertionSort(int arr[], int len){//二分插入排序//思想 : 首先找到有序列表中中间的元素,//arr[mid] mid = (left(有序列表的第一个元素下标) + right(有序列表的最后一个元素下标)) / 2 //将待插入元素于中间元素比较, 如果待插元素较大, 则应插在中间元素右边, 则将left 标为mid的后面, //再继续二分比较, 直到找到left的正确位置,然后将left元素后面的元素后移, 最后插入leftint left/*有序表中第一个元素下标*/, right/*有序表中最后的元素下标*/, mid/*中间元素下标*/;for (int i = 1; i < len; i++){//外层循环为数组长度, 这里从第二个元素开始插入, 因为一个元素不存在排序int temp = arr[i]; //取待插入元素left = 0; right = i - 1;while (left <= right){//确定left下标的循环, 不停的将当前段截成左右两段mid = (left + right) / 2; //mid为当前段的中间元素下标if (temp < arr[mid]){//如果待插元素比中间元素小, 将left 到 right段设置为原先mid段的左边right = mid - 1;}else{//否则, 将left到right段设置为原先mid段的右边left = mid+ 1;}}for (int j = i - 1; j >= left; j--){//将有序列表中left下标后的元素后移, 这里操作的就是整个有序列表了.arr[j + 1] = arr[j];}arr[left] = temp; //插入待排序元素}}


直接插入排序终级版->希尔排序:

设置一个步长,然后将在步长内的元素分组, 然后在分组内进行直接插入排序

void ShellSort(int arr[], int len){//希尔排序//恩想 : 设定一个步长, 然后将相隔该步长的元素分到一组,//进行比较,符合条件就交换,然后继续与该组前面的元素进行比较, //不符合条件就停止该组的比较int d; //步长, 不断减半, 直到为1int j; for (d = len / 2; d >= 1; d = d / 2){//外层为步长/2直到为1的循环次数for (int i = d; i < len; i++){//将i设置为当前步长, 并定为元素下标int temp = arr[i]; //设置待插入元素, 注意是从后入前的顺序比较, 待插入元素为该步长最后元素for (j = i - d; (j >= 0) && (arr[j] > temp); j = j - d){//设置当前比较元素, 当该组中前面的元素比较大时, 把较小元素插到该分组的前面arr[j + d] = arr[j]; //后移的位置为步长}arr[j + d] = temp;}}}


选择排序:

void SelectionSort(int arr[], int len){//选择排序//每次选出最小的元素与数组最前端的元素进行排序int min = 0; //最小元素的下标for (int i = 0; i < len - 1; i++){//外层循环为数组长度-1min = i; //min为当前元素下标for (int j = i + 1; j < len ; j++){//内层循环只在没有被选为最小元素的元素中进行选择if (arr[j] < arr[min]){//当前元素比"临时最小元素"小, 获得该较小元素下标min = j;}}if (min != i){//把当前元素(arr[i])与arr[min]互换, 因为这时的i肯定是在数组的前最前端元素int temp = arr[min];arr[min] = arr[i];arr[i] = temp;}}}


0 0