目录
冒泡排序
冒泡排序常规版本:
#include <iostream>
using namespace std;
void ipanel_bubble_sort(int *arr, int sz)
{
for(int j = (sz -1) ;j>0;j--)//j的边界到1就好,可以完成排序
{
for(int i = 0;i < j; i++)
{
if(arr[i] > arr[i+1])
{
int tmp;
tmp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = tmp;
}
}
}
}
int main()
{
int arr[] = {7, 1, 3, 4, 8, 5};
int index = 0;
int size = sizeof(arr)/ sizeof(int);
ipanel_bubble_sort(arr, size);
for(;index< size;index++)
cout << arr[index] << " " ;
}
冒泡排序常规版本不用临时变量(tmp)
#include <iostream>
using namespace std;
void bubble_sort(int *arr, int sz)
{
for(int j = (sz -1) ;j>0;j--)
{
for(int i = 0;i < j; i++)
{
if(arr[i] > arr[i+1])
{
arr[i] += arr[i+1];
arr[i+1] = arr[i] - arr[i+1];
arr[i] -= arr[i+1];
}
}
}
}
int main()
{
int arr[] = {7, 1, 3, 4, 8, 5};
int index = 0;
int size = sizeof(arr)/ sizeof(int);
bubble_sort(arr, size);
for(;index< size;index++)
cout << arr[index] << " ";
}
冒泡排序改进版本(加入exchange变量)
加入exchange标志变量,如果内部循环的时候,已经没有要交换顺序的操作,说明数组已经排好顺序,可以终止趟数。
#include <iostream>
using namespace std;
void ipanel_bubble_sort(int *arr, int sz)
{
for(int j = (sz -1) ;j>0;j--)
{
bool exchange = false;
for(int i = 0;i < j; i++)
{
if(arr[i] > arr[i+1])
{
int tmp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = tmp;
if(!exchange){exchange = true;}
}
}
if(!exchange) break;
}
}
int main()
{
int arr[] = {7,1,2,3,4,5,6};
int index = 0;
int size = sizeof(arr)/ sizeof(int);
ipanel_bubble_sort(arr, size);
for(;index< size;index++)
cout << arr[index] << " " ;
}
简单选择排序
#include <iostream>
using namespace std;
void swap(int &x, int &y)
{
int tmp = x;
x = y;
y = tmp;
}
void sel_sort(int *arr, int sz)//sz个数
{
for(int i = 0; i < (sz - 1); ++i)//sz-1趟
{
int k = i;
for(int j = i + 1; j <= (sz - 1); ++j)//找arr中最小数和arr[0]交换位置,后面以此类推
{
if(arr[j] < arr[k]) k = j;
}
if(k != i)//下标不相等才交换位置,否则不交换
{
swap(arr[i], arr[k]);
}
}
}
int main()
{
int arr[] = {7,10,2,30,14,5,0};
int size = sizeof(arr)/ sizeof(int);
sel_sort(arr, size);
for(int index = 0;index< size;index++)
cout << arr[index] << " " ;
}
三层for循环的插入排序(最原始插入排序)
#include <iostream>
using namespace std;
void in_sort(int *arr, int n)
{
for (int i = 1; i < n; ++i) {
if(arr[i] < arr[i-1]){
int tmp = arr[i];
for (int j = 0; j < i; ++j) {
if(tmp < arr[j]){
for (int k = i; k > j; --k) {
arr[k] = arr[k-1];
}
arr[j] = tmp;
break;
}
}
}
}
}
int main()
{
int arr[] = {11,22,0,9,8,100,33};
int size = sizeof(arr) / sizeof(int);
in_sort(arr, size);
for (int i = 0; i <size ; ++i) {
cout<< arr[i]<<" ";
}
cout<<endl;
}
插入排序
#include <iostream>
using namespace std;
//排序一和排序二逻辑上没有什么不同,只是while循环的写法不一样
void ins_sort_1(int *arr, int sz)
{
int tmp, j ;
for(int i = 1; i <= (sz-1); ++i ){
if (arr[i] < arr[i - 1]) {
tmp = arr[i];
j = i - 1;
do {
arr[j + 1] = arr[j];
--j;
}while (j >= 0 && tmp < arr[j]);
arr[j + 1] = tmp;
}
}
}
void ins_sort_2(int *arr, int sz)
{
for(int i = 1;i<sz;++i){//一趟完成之后前i+1个就是有序的
int key = arr[i];
int j = i -1;
while ((j>=0) && (key < arr[j])){
arr[j +1] =arr[j];
j--;
}
arr[j+1] = key;
}
}
int main()
{
int arr[] = {47, 15, 40, 28, 10, 2, 14, 25, 32, 29};
int size = sizeof(arr)/ sizeof(int);
//ins_sort_1(arr, size);
ins_sort_2(arr, size);
for(int index = 0;index< size;index++)
cout << arr[index] << " " ;
}
带哨兵的插入排序
#include <iostream>
using namespace std;
void in_sort_2(int *arr, int n)
{
for (int i = 2; i < n; ++i) {
int j;
if(arr[i] < arr[i-1]){
arr[0] = arr[i];
//arr[i] = arr[i-1];
for (j = i; arr[0] < arr[j-1]; --j) {
arr[j] = arr[j-1];
}
arr[j] = arr[0];
}
}
}
int main()
{
int arr[] = {0,11,22,0,90000,8,100,33};//arr[0]是哨兵,有两个作用:一方面是作为临时空间,另一方面是作为循环终止的条件。
int size = sizeof(arr) / sizeof(int);
in_sort_2(arr, size);
for (int i = 1; i <size ; ++i) {
cout<< arr[i]<<" ";
}
cout<<endl;
}
折半插入排序
#include <iostream>
using namespace std;
void half_ins_sort(int *arr, int n)
{
for (int i = 2; i < n; ++i) {
arr[0] = arr[i];
int lo = 1,hi = i-1;
while (lo <= hi ){
int mid = (lo + hi) / 2;
if(arr[0] < arr[mid])
hi = mid-1;
else
lo = mid +1;
}
for (int j = i; j >lo ; --j) {
arr[j] = arr[j-1];
}
arr[lo] =arr[0];
}
}
int main()
{
int arr[] = {0,11,22,0,90000,8,100,33};//arr[0]作为临时空间
int size = sizeof(arr) / sizeof(int);
half_ins_sort(arr, size);
for (int i = 1; i <size ; ++i) {
cout<< arr[i]<<" ";
}
cout<<endl;
}
插入排序的优化版本--希尔排序
#include <iostream>
using namespace std;
void shell_sort(int arr[],int len)
{
int gap, i, j;
int tmp;
for(gap = len >> 1;gap > 0;gap >>= 1){
for (int i = gap; i <len ; ++i) {
tmp = arr[i];
for (j = i-gap; j>=0 && arr[j] > tmp ; j -= gap) {
arr[j+gap] = arr[j];
}
arr[j+gap] = tmp;
}
}
}
int main()
{
int arr[] = {47, 15, 40, 28, 10, 2, 14};
int size = sizeof(arr)/ sizeof(int);
shell_sort(arr, size);
for(int index = 0;index< size;index++)
cout << arr[index] << " ";
cout<<endl;
}
希尔排序的时间复杂度和其步长有关,步长有多种选取方式,本例的步长使用的是(n/2)。当希尔排序的步长最后为1的时候,
其实就是插入排序,此时待排的序列,已经基本有序了。
希尔排序(自己规定增量序列)
#include <iostream>
using namespace std;
void shell_ins_sort (int *arr, int n, int gap)
{
int j;
for (int i = gap; i < n; ++i) {
if(arr[i] < arr[i-gap]){
int tmp = arr[i];
for(j = i-gap;j>=0&&tmp<arr[j];j -= gap){
arr[j+gap] = arr[j];
}
arr[j+gap] = tmp;
}
}
}
void shell_sort(int *arr, int n, int *gaps, int t)
{
for (int i = 0; i < t; ++i) {
shell_ins_sort(arr, n , gaps[i]);
}
}
int main()
{
int gaps[] = {5,3,2,1};
int arr[] = {11,22,0,90000,8,100,33};
int size = sizeof(arr) / sizeof(int);
shell_sort(arr,size,gaps,(sizeof(gaps) / sizeof(int)));
for (int i = 0; i <size ; ++i) {
cout<< arr[i]<<" ";
}
cout<<endl;
}
归并排序
#include <iostream>
using namespace std;
void merge_sort_recursive(int arr[], int reg[], int start, int end) {
if (start >= end)
return;
int len = end - start, mid = (len >> 1) + start;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
merge_sort_recursive(arr, reg, start1, end1);
merge_sort_recursive(arr, reg, start2, end2);
int k = start;
while (start1 <= end1 && start2 <= end2)
reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
while (start1 <= end1)
reg[k++] = arr[start1++];
while (start2 <= end2)
reg[k++] = arr[start2++];
for (k = start; k <= end; k++)
arr[k] = reg[k];
}
void merge_sort(int arr[], const int len) {
int reg[len];
merge_sort_recursive(arr, reg, 0, len - 1);
}
int main()
{
int arr[] = {2,3,5,6,8,7,4};
int size = sizeof(arr)/ sizeof(int);
merge_sort(arr, size);
for(int index = 0;index< size;index++)
cout << arr[index] << " ";
cout<<endl;
}
二路归并排序(参考别人的)
#include <iostream>
using namespace std;
void merge(int *a, int lo, int mi, int hi)
{
int nl = mi - lo + 1;//左边的长度
int nr = hi - mi;//右边的长度
int *L = new int[nl + 1];//空出一个哨兵的位置
int *R = new int[nr + 1];
L[nl] = 100000;//左边队列的哨兵
R[nr] = 100000;//右边队列的哨兵
int i, j, k;
for (i = 0; i < nl; i++) {
L[i] = a[lo + i];//把左边部分的值赋给一个保存左边值的临时队列
}
for (j = 0; j < nr; j++)
R[j] = a[mi + 1 + j];
//k从lo的位置开始
for (i = 0, j = 0, k = lo; k <= hi; k++) {
if (L[i] <= R[j]) {//把较小的值赋给主队列(用了哨兵这里可以少写两个循环)
a[k] = L[i];
i++;
}
else {
a[k] = R[j];
j++;
}
}
delete[]L;
delete[]R;
}
void mergeSort(int *a, int lo, int hi)
{
if (lo < hi) {
int mi = (lo + hi) >> 1;
mergeSort(a, lo, mi);
mergeSort(a, mi + 1, hi);
merge(a, lo, mi, hi);
}
}
int main()
{
int a[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};
int n = sizeof(a) / sizeof(a[0]);
int lo = 0;
int hi = n - 1;
mergeSort(a, lo, hi);
for (int i = 0; i <n ; ++i) {
cout<<a[i]<<" ";
}
}
严蔚敏版二路归并实现
#include <iostream>
using namespace std;
void Merge(int *SR, int *TR, int i, int m, int n)
{
int j = m+1;
int k = i;
for (;i<=m&&j<=n;++k){
if(SR[i] <= SR[j]){
TR[k] = SR[i++];
}
else{
TR[k] = SR[j++];
}
}
while (i<=m){
TR[k++] = SR[i++];
}
while (j<=n){
TR[k++] = SR[j++];
}
}
void Msort(int *SR, int *TR1, int s ,int t)
{
if(s == t){
TR1[s] = SR[s];
}
else{
int *TR2 = new int [100];
int m = (s + t) / 2;
Msort(SR, TR2, s, m);
Msort(SR,TR2,m+1,t);
Merge(TR2,TR1,s,m,t);
delete[]TR2;
}
}
int main()
{
int arr[] = {11,22,0,90000,8,11,33, 44, 56, 78, 1,4,5,7,6};
int size = sizeof(arr) / sizeof(int);
Msort(arr, arr, 0, size-1);//传两个一模一样的参数还是有点迷,真的是
for (int i =0; i <size ; ++i) {
cout<< arr[i]<<" ";
}
cout<<endl;
}
快速排序(挖坑法)
#include <iostream>
using namespace std;
int partion(int arr[], int lo, int hi)
{
int privot = arr[lo];
while (lo < hi)
{
while ((lo<hi)&&(privot <= arr[hi]))
hi--;
arr[lo] = arr[hi];
while ((lo< hi)&&(arr[lo])<= privot)
lo++;
arr[hi] = arr[lo];
}
arr[lo] = privot;//用privot填坑
return lo;
}
void QuickSort(int arr[], int lo, int hi)//QuickSort函数[ )
{
if (hi - lo < 2) return;//单元素区间,自然有序
int mid = partion(arr, lo, hi-1);
QuickSort(arr, lo, mid );
QuickSort(arr, mid + 1, hi);
}
int main()
{
int arr[] = {};
int size = sizeof(arr) / sizeof(int);
QuickSort(arr, 0, size);
for (int i = 0; i <size ; ++i) {
cout<<arr[i]<<" ";
}
}
堆排序实现
#include <stdio.h>
#include <stdlib.h>
void swap(int *a, int *b) {
int temp = *b;
*b = *a;
*a = temp;
}
void max_heapify(int arr[], int start, int end) {
// 建立父節點指標和子節點指標
int dad = start;
int son = dad * 2 + 1;
while (son <= end) { // 若子節點指標在範圍內才做比較
if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的
son++;
if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數
return;
else { // 否則交換父子內容再繼續子節點和孫節點比较
swap(&arr[dad], &arr[son]);
dad = son;
son = dad * 2 + 1;
}
}
}
void heap_sort(int arr[], int len) {
int i;
// 初始化,i從最後一個父節點開始調整
for (i = len / 2 - 1; i >= 0; i--)
max_heapify(arr, i, len - 1);
// 先將第一個元素和已排好元素前一位做交換,再重新調整,直到排序完畢
for (i = len - 1; i > 0; i--) {
swap(&arr[0], &arr[i]);
max_heapify(arr, 0, i - 1);
}
}
int main() {
int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
int len = (int) sizeof(arr) / sizeof(*arr);
heap_sort(arr, len);
int i;
for (i = 0; i < len; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
基数排序
#include <iostream>
using namespace std;
int maxbit(int data[], int n) //辅助函数,求数据的最大位数
{
int maxData = data[0]; ///< 最大数
/// 先求出最大数,再求其位数,这样有原先依次每个数判断其位数,稍微优化点。
for (int i = 1; i < n; ++i)
{
if (maxData < data[i])
maxData = data[i];
}
int d = 1;
int p = 10;
while (maxData >= p)
{
//p *= 10; // Maybe overflow
maxData /= 10;
++d;
}
return d;
/* int d = 1; //保存最大的位数
int p = 10;
for(int i = 0; i < n; ++i)
{
while(data[i] >= p)
{
p *= 10;
++d;
}
}
return d;*/
}
void radixsort(int data[], int n) //基数排序
{
int d = maxbit(data, n);
int *tmp = new int[n];
int *count = new int[10]; //计数器
int i, j, k;
int radix = 1;
for(i = 1; i <= d; i++) //进行d次排序
{
for(j = 0; j < 10; j++)
count[j] = 0; //每次分配前清空计数器
for(j = 0; j < n; j++)
{
k = (data[j] / radix) % 10; //统计每个桶中的记录数
count[k]++;
}
for(j = 1; j < 10; j++)
count[j] = count[j - 1] + count[j]; //将tmp中的位置依次分配给每个桶
for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中
{
k = (data[j] / radix) % 10;
tmp[count[k] - 1] = data[j];
count[k]--;
}
for(j = 0; j < n; j++) //将临时数组的内容复制到data中
data[j] = tmp[j];
radix = radix * 10;
}
delete []tmp;
delete []count;
}
int main()
{
int arr[] = {999, 33, 2, 52 ,90};
int size = sizeof(arr) / sizeof(int);
radixsort(arr, size);
for (int i = 0; i < size; ++i) {
cout<< arr[i]<< " ";
}
}
借助list,实现基数排序
#include <iostream>
#include <list>
using namespace std;
list<int> lt[10];
int maxbit(int data[], int n) //辅助函数,求数据的最大位数
{
int maxData = data[0]; ///< 最大数
/// 先求出最大数,再求其位数,这样有原先依次每个数判断其位数,稍微优化点。
for (int i = 1; i < n; ++i) {
if (maxData < data[i])
maxData = data[i];
}
int d = 1;
int p = 10;
while (maxData >= p) {
//p *= 10; // Maybe overflow
maxData /= 10;
++d;
}
return d;
}
int Getkey(int value, int k)
{
int key;
while(k>0)
{
key = value % 10;
value /= 10;
k--;
}
return key;
}
void Distrubute(int *ar, int n, int k)
{
for(int i=0; i<n; ++i)
{
int key = Getkey(ar[i], k);
lt[key].push_back(ar[i]);
}
}
void Collect(int *ar)
{
int n = 0;
list<int>::iterator it;
for(int i=0; i<10; ++i)
{
it = lt[i].begin();
while(it != lt[i].end())
{
ar[n++] = *it;
++it;
}
lt[i].clear();
}
}
void RadixSort(int *ar, int n)
{
int k = maxbit(ar,n);
for(int i=1; i<=k; ++i)
{
Distrubute(ar, n, i);
Collect(ar);
}
}
int main()
{
int arr[] = {11,22,0,8,11,33, 44, 56, 78, 1,4,5,7,6,10000,55555};
int size = sizeof(arr) / sizeof(int);
RadixSort(arr,size);
for (int i =0; i <size ; ++i) {
cout<< arr[i]<<" ";
}
cout<<endl;
}