算法题
Java实现:
https://blog.csdn.net/meibenxiang/article/details/92796909?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162790074316780255231156%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162790074316780255231156&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2 allfirst_rank_v2~rank_v29-2-92796909.pc_search_result_cache&utm_term=排序算法&spm=1018.2226.3001.4187
C++实现:
https://blog.csdn.net/kuaizi_sophia/article/details/87954222?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162795458816780274117377%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162795458816780274117377&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-1-87954222.pc_search_result_cache&utm_term=排序算法C%2B%2B&spm=1018.2226.3001.4187
一 冒泡排序
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个
- 从小到大
1 C++实现
#include<iostream>
using namespace std;
#include<string>
#include<vector>
// 冒泡排序
void bubbleSort(vector<int>& array) {
for (size_t i = 0; i < array.size(); i++) {
// 当前轮是否发生过交换事件标志位,若未发生交换,则表明列表已有序
bool isExchanged = false;
for (size_t j = 0; j < array.size() - i - 1; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
isExchanged = true;
}
}
if (!isExchanged){
break;
}
}
}
2 Java实现
public static int[] bubbleSort(int[] array){
if(array.length > 0){
for(int i = 0;i<array.length;i++){
for(int j = 0;j<array.length - 1 - i;j++){
if(array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
}
return array;
二 选择排序
- 搜索整个列表,找出最小项/最大项,若此项不为第1项,则与第1项交换位置
- 从小到大/从大到小
1 C++实现
// 选择排序
void selectSort(vector<int>& array){
for (size_t i = 0; i < array.size(); i++){
size_t minIndex = i;
for (size_t j = i + 1; j < array.size(); j++){
if (array[minIndex] > array[j]){
minIndex = j;
}
}
if (minIndex != i){
swap(array[i], array[minIndex]);
}
}
}
2 Java实现
public static int[] selectionSort(int[] array){
if(array.length > 0){
for(int i = 0;i<array.length;i++){
int minIndex = i;
for(int j = i;j<array.length;j++){
//遍历未剩余未排序元素中继续寻找最小元素
if(array[j] < array[minIndex]){
minIndex = j;
}
}
if(minIndex != i){
int temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
}
}
return array;
}
三 插入排序
- 从小到大
- 通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入
1 c++实现
// 插入排序
void insertionSort(vector<int>& array){
// i 代表无序序列首元素(无序序列前为有序序列)
size_t i = 1;
while (i < array.size()){
size_t j = i - 1;
int itermToInsert = array[i];
while (j >= 0){
if (array[j] >= itermToInsert){
array[j + 1] = array[j];
j--;
}
else{
break;
}
}
array[j + 1] = itermToInsert;
i++;
}
}
2 Java实现
public static int[] insertSort(int[] array){
if(array.length > 0){
for(int i = 0 ;i<array.length - 1;i++){
int current = array[i+1];
int index = i;
while(index >= 0 && current < array[index]){
array[index + 1] = array[index];
index--;
}
array[index+1] = current;
}
}
return array;
}
四 希尔排序
- 一种插入排序,缩小增量排序
- 希腊增量Java实现
- 从小到大
- 选择增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择我们可以用一个序列来表示,{n/2,(n/2)/2…1},称为增量序列
- 假设一共10个数,第一次10/2分为5组,第二次5/2分为2组,第三次2/2为1组,最后再进行简单的微调
1 c++实现
// 希尔排序
void shellSort(vector<int>& array){
int n = array.size();
for (int gap = n / 2; gap >= 1; gap /= 2){
for (int i = gap; i < n; i++){
// 使用插入排序算法,将元素依次插入所在小组的已排序列表中
// 待插入元素
int itermToInsert = array[i];
int j = i - gap;
while (j >= 0 && array[j] >= itermToInsert){
array[j + gap] = array[j];
j -= gap;
}
array[j + gap] = itermToInsert;
}
}
}
2 Java实现
public static int[] shellSort(int[] array){
if(array.length > 0){
int len = array.length;
int gap = len / 2;
while(gap > 0){
for(int i = gap;i < len;i++){
int temp = array[i];
int index = i - gap;
while(index >= 0 && array[index] > temp){
array[index + gap] = array[index];
index -= gap;
}
array[index + gap] = temp;
}
gap /= 2;
}
}
return array;
}
五 归并排序
- 分治法
- 把长度为n的输入序列分成两个长度为n/2的子序列,对这两个子序列分别采用归并排序,将两个排序好的子序列合并成一个最终的排序序列
1 c++实现
// 归并排序
// 合并两有序序列,两序列分别为array的0到mid部分和mid+1到末尾部分。
void merge(vector<int>& array, vector<int>& copyArray, int left, int right) {
int mid = (left + right) / 2;
int i = left, j = mid + 1, k = 0;
while (i <= mid || j <= right) {
if (i > mid) {
copyArray[k] = array[j];
j++;
}
else if (j > right) {
copyArray[k] = array[i];
i++;
}
else if (array[i] > array[j]) {
copyArray[k] = array[j];
j++;
}
else {
copyArray[k] = array[i];
i++;
}
k++;
}
for (size_t i = left; i <= right; i++) {
array[i] = copyArray[i - left];
}
}
void mergeSortHelp(vector<int>& array, vector<int>& copyArray, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSortHelp(array, copyArray, left, mid);
mergeSortHelp(array, copyArray, mid + 1, right);
merge(array, copyArray, left, right);
}
}
// 归并排序 递归实现
void mergeSort(vector<int>& array) {
vector<int> copyArray(array);
mergeSortHelp(array, copyArray, 0, array.size() - 1);
}
2 Java实现
public static int[] MergeSort(int[] array){
if(array.length < 2){
return array;
}
int mid = array.length /2;
int[] left = Arrays.copyOfRange(array, 0, mid);
int[] right = Arrays.copyOfRange(array, mid, array.length);
return merge(MergeSort(left),MergeSort(right));
}
public static int[] merge(int[] left,int[] right){
int[] result = new int[left.length + right.length];
for(int index = 0,i = 0, j = 0;index < result.length;index++){
if(i >= left.length){
result[index] = right[j++];
}else if(j >= right.length){
result[index] = left[i++];
}else if(left[i] > right[j]){
result[index] = right[j++];
}else{
result[index] = left[i++];
}
}
return result;
}
六 快速排序
- 通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序
- 从数列中挑出一个元素,称为 “基准”(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
- 从小到大
1 c++实现
// 快速排序(递归)
// 选则最左端、最右端和中间位置3元素的中值作为基准值,并将3元素排序,返回基准值
int medianPovit(vector<int>& array, int left, int mid, int right){
if (array[left] > array[mid]){
swap(array[mid], array[left]);
}
if (array[left] > array[right]){
swap(array[left], array[right]);
}
if (array[mid] > array[right]){
swap(array[mid], array[right]);
}
return array[mid];
}
// 分区,返回基准索引
int partition(vector<int>& array, int left, int right) {
// 中间位置索引
int mid = (left + right) / 2;
// 基准值(此时基准值对应索引为mid)
int povit = medianPovit(array, left, mid, right);
// 将基准值与倒数第二个元素交换
array[mid] = array[right - 1];
array[right - 1] = povit;
int i = left, j = right - 1;
while (i < j) {
if (array[i] < povit) {
i++;
}
else if (array[j] >= povit) {
j--;
}
else {
swap(array[i], array[j]);
}
}
// 交换基准值和i位置元素
swap(array[i], array[right - 1]);
return i;
}
void quickSortHelp(vector<int>& array, int left, int right) {
if (left < right) {
int pivotLoction = partition(array, left, right);
quickSortHelp(array, left, pivotLoction - 1);
quickSortHelp(array, pivotLoction + 1, right);
}
}
// 快速排序
void quickSort(vector<int>& array) {
quickSortHelp(array, 0, array.size() - 1);
}
2 Java实现
public static void QuickSort(int[] array,int low,int hight){
//if (array.length < 1 || low < 0 || hight >= array.length || low > hight) return null;
if(low < hight){
int privotpos = partition(array,low,hight);
QuickSort(array,low,privotpos - 1);
QuickSort(array,privotpos + 1,hight);
}
}
public static int partition(int[] array,int low,int hight){
int privot = array[low];
while(low < hight){
while(low < hight && array[hight] >= privot) --hight;
array[low] = array[hight];
while(low < hight && array[low] <= privot) ++low;
array[hight] = array[low];
}
array[low] = privot;
return low;
}
七 堆排序 Heap Sort
- 堆:可以被看做一棵完全二叉树的数组对象
- 将待排序列构造成一个大顶堆(或小顶堆),整个序列的最大值(或最小值)就是堆顶的根结点,将根节点的值和堆数组的末尾元素交换,此时末尾元素就是最大值(或最小值),然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值(或次小值),如此反复执行,最终得到一个有序序列
- 满二叉树:一棵深度为k且有2k次方-1个结点的二叉树
- 完全二叉树:如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同
在这里插入代码片// 堆排序
// 调整堆,根元素沿树向下移动,直至其合适位置,first和last分别为堆顶和堆底在数组array中的索引
void moveDown(vector<int>& array, int first, int last){
// first的左子节点索引
int curIndex = first * 2 + 1;
while (curIndex <= last){
// 若first有2子节点,令curIndex为其值最大子节点索引
if (curIndex < last && array[curIndex] < array[curIndex + 1]){
curIndex++;
}
// 若根节点值小于子节点值,则交换
if (array[first] < array[curIndex]){
swap(array[first], array[curIndex]);
first = curIndex;
curIndex = first * 2 + 1;
}
else{
break;
}
}
}
// 用数组实现堆
void buildHeap(vector<int>& array){
// 最后一个非叶节点的节点索引
int i = array.size() / 2 - 1;
while (i >= 0){
moveDown(array, i, array.size() - 1);
i--;
}
}
// 堆排序
void heapSort(vector<int>& array){
// 生成堆
buildHeap(array);
// 堆顶、底索引
int first = 0, last = array.size() - 1;
while (first <= last){
swap(array[first], array[last]);
last--;
moveDown(array, first, last);
}
}
2 Java实现
public static int[] heapSort(int[] array){
int len = array.length;
//初始化堆,构造一个最大堆
for(int i = (len/2 - 1);i >= 0;i--){
heapAdjust(array,i,len);
}
//将堆顶的元素和最后一个元素交换,并重新调整堆
for(int i = len - 1;i > 0;i--){
int temp = array[i];
array[i] = array[0];
array[0] = temp;
heapAdjust(array,0,i);
}
return array;
}
八 计数排序
- 将输入的数据值转化为键存储在额外开辟的数组空间中
1 c++实现
// 计数排序
void countSort(vector<int>& array){
if (array.empty()){
return;
}
//找出最大最小值
int min = array.front(),max = array.front();
for (int i = 1; i < array.size(); i++){
if (min > array[i]){
min = array[i];
}
else if (max < array[i]){
max = array[i];
}
}
// 记录各元素出现次数
vector<int> counts(max - min + 1);
for (int i = 0; i < array.size(); i++){
counts[array[i] - min]++;
}
// 根据记录的次数输出对应元素
int index = 0;
for (int j = 0; j < counts.size(); j++){
int n = counts[j];
while (n--){
array[index] = j + min;
index++;
}
}
}
2 Java实现
九 桶排序
1 c++实现
// 桶排序
void bucketSort (vector<int>& array, int bucketCount){
if (array.empty()){
return;
}
// 找出最大最小值
int max = array.front(), min = array.front();
for (int i = 1; i < array.size(); i++){
if (min > array[i]){
min = array[i];
}
else if (max < array[i]){
max = array[i];
}
}
// 将待排序的各元素分入对应桶中
vector<vector<int>> buckets(bucketCount);
int bucketSize = ceil((double)(max - min + 1) / bucketCount);
for (int i = 0; i < array.size(); i++){
int bucketIndex = (array[i] - min) / bucketSize;
buckets[bucketIndex].push_back(array[i]);
}
// 对各桶中元素进行选择排序
int index = 0;
for (vector<int> bucket : buckets){
if (!bucket.empty()){
// 使用选择排序算法对桶内元素进行排序
selectSort(bucket);
for (int value : bucket){
array[index] = value;
index++;
}
}
}
}
// 桶排序
void bucketSort (vector<int>& array){
bucketSort (array, array.size() / 2);
}
2 Java实现
十 基数排序
1 c++实现
// 基数排序 (只适用于正数,此处不适用)
void radixSort(vector<int>& array){
// 当前位数
int curdigit = 10;
// 当前位是否已超过最高为
bool isOverHighest = false;
while (!isOverHighest){
isOverHighest = true;
// 利用分桶的思想来实现按各位进行排序
vector<vector<int>> buckets(10);
for (int curVal : array){
int bucketIndex = curVal % curdigit - curVal % (curdigit / 10);
buckets[bucketIndex].push_back(curVal);
if (isOverHighest && curVal / curdigit){
isOverHighest = false;
}
}
// 按照桶的顺序,将各桶内元素拼接起来
int index = 0;
for (vector<int> bucket : buckets){
for (int value : bucket){
array[index] = value;
index++;
}
}
curdigit *= 10;
}
}