赞
踩
目录
排序:按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作;
稳定性:若存在多个具有相同关键字的对象,经过排序,其相对位置次序保持不变,则称此算法稳定;
内部排序:数据元素全部放在内存中的排序;
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内存之间移动数据的排序;
一,直接插入排序
逻辑思路:
特性:
- //直接插入法
- void InsertSort(int* arr, int n)
- {
- int i = 0;
- for (i; i < n - 1; i++)
- {
- //单次插入
- int end = i;
- int tmp = arr[end + 1];
- while (end >= 0)
- {
- if (arr[end] > tmp)
- {
- arr[end + 1] = arr[end];
- --end;
- }
- else
- break;
- }
- arr[end + 1] = tmp;
- }
- }
二,希尔排序(又称缩小增量法)
逻辑思路:
注:
特性:
- //希尔排序
- void ShellSort(int* arr, int n)
- {
- int gap = n;
- //gap>1为预排序,gap=1为直接排序
- while (gap > 1)
- {
- //gap每三倍的逐渐减小,+1保证最后一次排序gap为1
- gap = gap / 3 + 1;
- //预排序(多组并排)
- int i = 0;
- for (i; i < n - gap; i++)
- {
- int end = i;
- int tmp = arr[end + gap];
- while (end >= 0)
- {
- if (tmp < arr[end])
- {
- arr[end + gap] = arr[end];
- end -= gap;
- }
- else
- break;
- }
- arr[end + gap] = tmp;
- }
- }
- }
三,直接选择排序
逻辑思路:
特性:
- //直接选择排序
- void SelectSort(int* arr, int n)
- {
- int begin = 0;
- int end = n - 1;
- while (begin < end)
- {
- int mini = begin;
- int maxi = begin;
- for (int i = begin; i <= end; i++)
- {
- if (arr[i] < arr[mini])
- mini = i;
- if (arr[i] > arr[maxi])
- maxi = i;
- }
- Swap(arr + begin, arr + mini);
- //但首元素即为最大值时,此时值已被交换需校正
- if (begin == maxi)
- maxi = mini;
- Swap(arr + end, arr + maxi);
- begin++;
- end--;
- }
- }
四,堆排序
逻辑思路:
特性:
- //建堆排序
- void HeapSort(int* arr, int n)
- {
- //建堆 - O(N)
- int i = (n - 1 - 1) / 2; //最后节点的父节点
- for (i; i >= 0; i--)
- {
- AdjustDown(arr, n, i);
- }
-
- //排序 - O(N*log(N))
- int end = n - 1;
- while (end)
- {
- Swap(arr, arr + end);
- AdjustDown(arr, end, 0);
- end--;
- }
- }
五,冒泡排序
逻辑思路:
特性:
- //冒泡排序
- void BubbleSort(int* arr, int n)
- {
- for (int i = 0; i < n - 1; i++)
- {
- int exchange = 0;
- for (int j = 0; j < n - 1 - i; j++)
- {
- if (arr[j] > arr[j + 1])
- {
- Swap(arr + j, arr + j + 1);
- exchange = 1;
- }
- }
- if (!exchange)
- break;
- }
- }
六,快速排序
一种二叉树结构的交换排序;
逻辑思路:
特性:
按基准值将序列划分尾左右子序列方法:
- 左右指针法(Hoare):
- 如以左边首个元素为key;
- 随后最右边right先向左走,遇到比key小的停下;
- 在最左边left向右走,遇到比key大的停下;
- 此时左右元素交换;
- 然后重复操作,直到left等于right为止;
- 挖坑法:
- 如以左边首个元素为key,并保存此元素;
- 随后最右边right先向左走,遇到比key小的停下并将此元素填入key位置,此位置在标记为key;
- 在最左边left向右走,遇到比key大的停下并将此元素填入key位置,此位置在标记为key;
- 然后重复操作,直到left等于right为止,最后把最初key元素填入最后的key位置即可;
- 前后指针法:
- 如以左边首个元素为key,此元素标记为前指针prev,下个元素标记为后指针cur;
- cur先向后走,遇到比key小的停下,prev++,此时交换prev与cur位置的元素;
- 然后重复操作,直到序列尾为止,最后交换key与prev位置元素即可;
- //针对有序序列,时间复杂度为O(N^2),会很大影响效率;
- //三数取中法
- int GetMidIndex(int* arr, int left, int right)
- {
- int mid = left + (right - left) / 2; //(left+right)/2,left+right可能会溢出
- if (arr[left] < arr[mid])
- {
- if (arr[mid] < arr[right])
- return mid;
- else if (arr[left] < arr[right])
- return right;
- else
- return left;
- }
- else
- {
- if (arr[mid] > arr[right])
- return mid;
- else if (arr[left] < arr[right])
- return left;
- else
- return right;
- }
- }
- //左右指针法
- int PartSort(int* arr, int left, int right)
- {
- int midi = GetMidIndex(arr, left, right);
- Swap(arr + left, arr + midi);
-
- int keyi = left;
- while (left < right)
- {
- while (left < right && arr[right] >= arr[keyi])
- right--;
- while (left < right && arr[left] <= arr[keyi])
- left++;
- Swap(arr + left, arr + right);
- }
- Swap(arr + keyi, arr + left);
- return left;
- }
- //挖坑法
- int PartSort(int* arr, int left, int right)
- {
- //三数取中
- int midi = GetMidIndex(arr, left, right);
- Swap(arr + left, arr + midi);
-
- int keyi = left;
- int key = arr[keyi];
- while (left < right)
- {
- while (left < right && arr[right] >= key)
- right--;
- arr[keyi] = arr[right];
- keyi = right;
-
- while (left < right && arr[left] <= key)
- left++;
- arr[keyi] = arr[left];
- keyi = left;
- }
- arr[keyi] = key;
- return keyi;
- }
- //前后指针法
- int PartSort(int* arr, int left, int right)
- {
- //三数取中
- int midi = GetMidIndex(arr, left, right);
- Swap(arr + left, arr + midi);
-
- int keyi = left;
- int prev = left;
- int cur = left + 1;
- while (cur <= right)
- {
- if (arr[cur] < arr[keyi] && ++prev != cur)
- Swap(arr + prev, arr + cur);
- cur++;
- }
- Swap(arr + prev, arr + keyi);
- return prev;
- }
- //快速排序
- void QuickSort(int* arr, int left, int right)
- {
- if (left < right)
- {
- int keyi = PartSort(arr, left, right);
- QuickSort(arr, left, keyi - 1);
- QuickSort(arr, keyi + 1, right);
- }
- }
快速排序非递归
逻辑思路:
注:
- //快速排序非递归
- void QuickSortNonR(int* arr, int left, int right)
- {
- Stack st; //创建栈st
- StackInit(&st); //初始化栈
- StackPush(&st, left); //记录区间(入栈)
- StackPush(&st, right); //记录区间(入栈)
-
- while (!StackEmpty(&st))
- {
- right = StackTop(&st);
- StackPop(&st);
- left = StackTop(&st);
- StackPop(&st);
- int keyi = PartSort(arr, left, right);
- if (keyi + 1 < right)
- {
- StackPush(&st, right);
- StackPush(&st, keyi + 1);
- }
- if (left < keyi - 1)
- {
- StackPush(&st, keyi - 1);
- StackPush(&st, left);
- }
- }
- StackDestroy(&st);
- }
七,归并排序
逻辑思路:
特性:
- //归并排序
- void _MergeSort(int* arr, int left, int right, int* tmp)
- {
- if (left >= right)
- return;
- int mid = (left + right) / 2;
- _MergeSort(arr, left, mid, tmp);
- _MergeSort(arr, mid + 1, right, tmp);
- //归并
- int begin1 = left, end1 = mid;
- int begin2 = mid + 1, end2 = right;
- //排序
- int index = left;
- while (begin1 <= end1 && begin2 <= end2)
- {
- if (arr[begin1] < arr[begin2])
- tmp[index++] = arr[begin1++];
- else
- tmp[index++] = arr[begin2++];
- }
- while(begin1 <= end1)
- tmp[index++] = arr[begin1++];
- while (begin2 <= end2)
- tmp[index++] = arr[begin2++];
- //最后还原到原数组
- for (int i = 0; i <= right; i++)
- arr[i] = tmp[i];
- }
-
- void MergeSort(int* arr, int n)
- {
- int* tmp = (int*)malloc(sizeof(int) * n);
- _MergeSort(arr, 0, n - 1, tmp);
- free(tmp);
- }
归并排序非递归
- //归并非递归排序
- void MergeSortNonR(int* arr, int n)
- {
- int* tmp = (int*)malloc(sizeof(int) * n);
-
- int grpNum = 1;
- while (grpNum < n)
- {
- for (int i = 0; i < n; i += grpNum * 2)
- {
- //归并
- int begin1 = i, end1 = i + grpNum - 1;
- int begin2 = i + grpNum, end2 = i + grpNum * 2 - 1;
- //修正越界,设置为一个无效区间
- if (begin2 >= n)
- {
- begin2 = n + 1;
- end2 = n;
- }
- if (end2 >= n)
- end2 = n - 1;
- //排序
- int index = begin1;
- while (begin1 <= end1 && begin2 <= end2)
- {
- if (arr[begin1] < arr[begin2])
- tmp[index++] = arr[begin1++];
- else
- tmp[index++] = arr[begin2++];
- }
- while (begin1 <= end1)
- tmp[index++] = arr[begin1++];
- while (begin2 <= end2)
- tmp[index++] = arr[begin2++];
- }
- //最后还原到原数组
- for (int i = 0; i < n; i++)
- arr[i] = tmp[i];
-
- grpNum *= 2;
- }
- }
八,计数排序(非比较排序)
逻辑思路:
特性:
- //计数排序
- void CountSort(int* arr, int n)
- {
- //获取最值
- int min = arr[0], max = arr[0];
- for (int i = 0; i < n; i++)
- {
- if (arr[i] < min)
- min = arr[i];
- if (arr[i] > max)
- max = arr[i];
- }
- //相对映射
- int range = max - min + 1;
- int* count = (int*)calloc(range, sizeof(int));
- //统计次数
- for (int i = 0; i < n; i++)
- {
- count[arr[i] - min]++;
- }
- //排序,还原数组
- int i = 0;
- for (int j = 0; j < range; j++)
- {
- while (count[j]--)
- arr[i++] = j + min;
- }
- }
九,基数排序(非比较排序)
省略!!!
有兴趣可自行搜索!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。