目录
一、基本概念
二、排序的分类
三、排序算法的好坏的衡量
四、五类内排序
插入排序
直接插入排序
演示:
关键代码:
完整代码
结果:
插入排序算法分析:
带哨兵的插入排序
举例:
关键代码
完整代码
折半插入排序
演示
关键代码
完整代码
结果
折半插入排序(监视哨)
关键代码
完整代码
折半插入排序的算法分析
希尔排序 (Shell Sort)
演示
举例
关键代码
完整代码
结果
希尔排序算法分析
交换排序
冒泡排序(Bubble Sort)
演示
举例
关键代码
完整代码
结果
冒泡排序算法分析
快速排序
关键代码
完整代码
结果
选择排序
简单选择排序
关键代码
完整代码
堆积树排序法
演示
关键代码1
完整代码1
结果1 编辑
改进关键代码2
完整代码2
归并排序
演示
关键代码1
完整代码1
关键代码2
完整代码2
基数排序
关键代码
一、基本概念
二、排序的分类

三、排序算法的好坏的衡量
四、五类内排序
插入排序
直接插入排序

template
void Swap(T& a, T& b)//交换
{T tmp;tmp = a;a = b;b = tmp;
}template
void Inser(T data[])
{for (int i = 1; i < size; i++)//i为扫描次数{int tmp = data[i];for (int j = i-1; j >=0; j--)//用j定位比较的元素{if (tmp < data[j]){Swap(data[j+1], data[j]);}}cout << "第" << i << "次扫描:";print(data);}
}
#include
#include
using namespace std;
#define size 5
template
void print(T data[])
{for (int i = 0; i < size; i++){cout << data[i] << " ";}cout << endl;
}
template
void Swap(T& a, T& b)//交换
{T tmp;tmp = a;a = b;b = tmp;
}template
void Inser(T data[])
{for (int i = 1; i < size; i++)//i为扫描次数{int tmp = data[i];for (int j = i - 1; j >= 0; j--)//用j定位比较的元素{if (tmp < data[j]){Swap(data[j + 1], data[j]);}}cout << "第" << i << "次扫描:";print(data);}
}int main()
{int data[] = { 55,23,87,62,16 };cout << "排序前的顺序:" << endl;print(data);Inser(data);cout << "排序后的顺序:" << endl;print(data);return 0;
}



带哨兵的插入排序

template
void Insert2(T data[])
{for (int i = 2; i < size; i++){data[0] = data[i];for (int j = i - 1; data[0] < data[j]; j--){Swap(data[j + 1], data[j]);}cout << "第" << i-1 << "次扫描:";print(data);}
}
#include
#include
using namespace std;
#define size 6
template
void print(T data[])
{for (int i = 1; i < size; i++){cout << data[i] << " ";}cout << endl;
}
template
void Swap(T& a, T& b)//交换
{T tmp;tmp = a;a = b;b = tmp;
}
template
void Insert2(T data[])
{for (int i = 2; i < size; i++){data[0] = data[i];for (int j = i - 1; data[0] < data[j]; j--){Swap(data[j + 1], data[j]);}cout << "第" << i-1 << "次扫描:";print(data);}
}int main()
{int data[size];cout << "请依次输入5个数据:";for (int i = 1; i < size; i++){cin >> data[i];}cout << "排序前的顺序:" << endl;print(data);Insert2(data);cout << "排序后的顺序:" << endl;print(data);return 0;
}
折半插入排序

template
void BinSort(T data[])
{for (int i = 1; i < size; i++)//扫描次数(需要排序的元素个数){T tmp = data[i];//先将data[i]保存在tmp中int low = 0, high = i - 1;int mid = 0;while (low <= high)//寻找插入位置{mid = (low + high) / 2;if (tmp <= data[mid]){high = mid - 1;}else{low = mid + 1;}}//循环结束,high+1为插入位置for (int j = i - 1; j >= high + 1; j--)//移动元素{data[j + 1] = data[j];}data[high + 1] = tmp;cout << "第" << i << "次扫描:" ;print(data);}
}
#include
#include
using namespace std;
#define size 11
template
void print(T data[])
{for (int i = 0; i < size; i++){cout << data[i] << " ";}cout << endl;
}
template
void BinSort(T data[])
{for (int i = 1; i < size; i++)//扫描次数(需要排序的元素个数){T tmp = data[i];//先将data[i]保存在tmp中int low = 0, high = i - 1;int mid = 0;while (low <= high)//寻找插入位置{mid = (low + high) / 2;if (tmp <= data[mid]){high = mid - 1;}else{low = mid + 1;}}//循环结束,high+1为插入位置for (int j = i - 1; j >= high + 1; j--)//移动元素{data[j + 1] = data[j];}data[high + 1] = tmp;cout << "第" << i << "次扫描:" ;print(data);}
}int main()
{//int data[] = { 3,5,7,10,16,23,29,32,54,83,96 };int data[] = { 96,83,54,32,29,23,16,10,7,5,3 };cout << "排序前的顺序:" << endl;print(data);BinSort(data);cout << "排序后的顺序:" << endl;print(data);return 0;
}

折半插入排序(监视哨)
template
void BinSort(T data[])
{for (int i = 2; i < size; i++){data[0] = data[i];//下标为0的位置放即将插入的元素(哨兵)int low = 0, high = i - 1;while (low <= high){int mid = (low + high) / 2;//折半if (data[0]<=data[mid]){high = mid - 1;//插入点在低半区}else{low = mid + 1;}}for (int j = i - 1; j >= low; j--){data[j + 1] = data[j];}data[low] = data[0];}
}
#include
#include
using namespace std;
#define size 12
template
void print(T data[])
{for (int i = 1; i < size; i++){cout << data[i] << " ";}cout << endl;
}template
void BinSort(T data[])
{for (int i = 2; i < size; i++){data[0] = data[i];//下标为0的位置放即将插入的元素(哨兵)int low = 0, high = i - 1;while (low <= high){int mid = (low + high) / 2;//折半if (data[0]<=data[mid]){high = mid - 1;//插入点在低半区}else{low = mid + 1;}}for (int j = i - 1; j >= low; j--){data[j + 1] = data[j];}data[low] = data[0];}
}
int main()
{int data[size] ;cout << "请依次输入"<> data[i];}cout << "排序前的顺序:" << endl;print(data);BinSort(data);cout << "排序后的顺序:" << endl;print(data);return 0;
}
折半插入排序的算法分析
次关键码比较,才能确定它应插入的位置。 希尔排序 (Shell Sort)
void ShellSort(int *data, int n, int delta)//一趟希尔排序
{for (int i = delta; i
#include
#include
using namespace std;
void swap(int& a, int& b)//交换
{int temp = a;a = b;b = temp;
}
void print(int* data, int n)//打印
{for (int i = 0; i < n; i++){cout << data[i] << " ";}cout << endl;
}
void ShellSort(int *data, int n, int delta)//一趟希尔排序
{for (int i = delta; i

希尔排序算法分析
交换排序
冒泡排序(Bubble Sort)


void BubbleSorta(int* data, int n)//冒泡排序
{for (int i = n - 1; i > 0; i--)//扫描次数{for (int j = 0; j < i; j++)//比较,交换次数{if (data[j] > data[j + 1]){swap(data[j], data[j + 1]);}}cout << "第" << n - i << "次扫描:";print(data, n);}
}
#include
#include
using namespace std;
void swap(int& a, int& b)//交换
{int tmp = a;a = b;b = tmp;
}
void print(int* data, int n)//打印
{for (int i = 0; i < n; i++){cout << data[i] << " ";}cout << endl;
}
void BubbleSorta(int* data, int n)//冒泡排序
{for (int i = n - 1; i > 0; i--)//扫描次数{for (int j = 0; j < i; j++)//比较,交换次数{if (data[j] > data[j + 1]){swap(data[j], data[j + 1]);}}cout << "第" << n - i << "次扫描:";print(data, n);}
}int main()
{int a[] = { 6,5,9,7,2,8 };cout << "排序前:";print(a, 6);BubbleSorta(a, 6);cout << "排序后:";print(a, 6);return 0;
}

void BubbleSorta(int* data, int n)//冒泡排序
{for (int i = n - 1; i > 0; i--)//扫描次数{int flag = 0;//flag用来判断是否执行了数据交换for (int j = 0; j < i; j++)//比较,交换次数{if (data[j] > data[j + 1]){swap(data[j], data[j + 1]);flag++;}}cout << "第" << n - i << "次扫描:";print(data, n);if (flag == 0)//当执行完依次扫描判断是否执行过数据交换操作,如果没有执行过数据交换操作//表示此时数列已经完成了排序,故可直接跳出循环break;}
}
冒泡排序算法分析
;最好情况只需扫描一次,若发现没有进行数据交换的操作,则表示已经排序完成,所以只进行n-1次比较,时间复杂度为 
快速排序
int partition(int* data, int i, int j)
{int tmp = data[i];while (i < j){while (i=tmp)//从右边找比基准数小的数字{j--;}if (i < j){data[i] = data[j];}while (i < j && data[i] <= tmp){i++;}if (i < j){data[j] = data[i];}}data[i] = tmp;//将tmp的值赋值给i和j重合的位置return i;
}
void QuickSort(int* data, int i, int j)
{if (i < j){int x = partition(data, i, j);QuickSort(data, i, x - 1);//给基准数左边数据排序QuickSort(data, x + 1, j);//给右边排序}
}
#include
#include
using namespace std;
int partition(int* data, int i, int j)
{int tmp = data[i];while (i < j){while (i=tmp)//从右边找比基准数小的数字{j--;}if (i < j){data[i] = data[j];}while (i < j && data[i] <= tmp){i++;}if (i < j){data[j] = data[i];}}data[i] = tmp;//将tmp的值赋值给i和j重合的位置return i;
}
void QuickSort(int* data, int i, int j)
{if (i < j){int x = partition(data, i, j);QuickSort(data, i, x - 1);//给基准数左边数据排序QuickSort(data, x + 1, j);//给右边排序}
}
void print(int* data,int n)
{for (int i = 0; i < n; i++){cout << data[i] << " ";}cout << endl;
}
int main()
{int a[] = { 35,10, 42, 3, 79, 12, 62, 18, 51, 23 };cout << "排序前:";print(a, 10);QuickSort(a, 0, 9);cout << "排序后:";print(a, 10);return 0;
}

选择排序
简单选择排序
void SelectionSort(int* data, int n)
{for (int i = 0; i <=n-1; i++)//扫描次数{int min = data[i];int k = i;//用k保存最小值的下标for (int j = i; j < n; j++){if (data[j] < min){min = data[j];k = j;}}swap(data[i], data[k]);}
}
#include
#include
using namespace std;
void swap(int& a, int& b)
{int tmp;tmp = a;a = b;b = tmp;
}
void SelectionSort(int* data, int n)
{for (int i = 0; i <=n-1; i++)//扫描次数{int min = data[i];int k = i;//用k保存最小值的下标for (int j = i; j < n; j++){if (data[j] < min){min = data[j];k = j;}}swap(data[i], data[k]);}
}
void print(int* data, int n)
{for (int i = 0; i < n; i++){cout << data[i] << " ";}cout << endl;
}
int main()
{int a[] = { 55,23,87,62,16 };cout << "排序前:";print(a, 5);SelectionSort(a, 5);cout << "排序后:";print(a, 5);return 0;
}
堆积树排序法


void HeadAdjust(int* data, int k, int n)//将以k为根的子树调整为大堆积根
{int tmp = data[k];int j ;if (2 * k + 2 < n){if (data[k] >= MAX(data[2 * k + 1], data[2 * k + 2]))//根结点大于其两个孩子结点{;}else if (data[2 * k + 1] > data[2 * k + 2])//左孩子结点的值大于右孩子结点{j = 2 * k + 1;swap(data[k], data[2 * k + 1]);for (int i = j; i < n; i = i * 2 + 1){HeadAdjust(data, i, n);}}else{j = 2 * k + 2;swap(data[k], data[2 * k + 2]);for (int i = j; i < n; i = i * 2 + 2){HeadAdjust(data, i, n);}}}else if (2 * k + 1 < n)//以k为根结点的时候,只有左孩子结点的时候{if (data[k] < data[2 * k + 1]){swap(data[k], data[2 * k + 1]);}}}void BulidHeap(int* data, int n)//建立大堆积树
{for (int i = (n - 2) / 2; i >= 0; i--)//(n-2)/2是树中第一个非叶子结点的下标{HeadAdjust(data, i, n);}
}
void HeadSort(int* data, int n)//基于大堆积树排序
{BulidHeap(data, n);//建立初始大堆积树//print(data, n);cout << "排序后:";for (int i = n - 1; i > 0; i--){cout << data[0] << " ";swap(data[0], data[i]);BulidHeap(data, i);//print(data, i);}cout << data[0];
}
#include
#include
using namespace std;
void swap(int& a, int& b)//交换
{int tmp;tmp = a;a = b;b = tmp;
}
int MAX(int& a, int& b)//求最大值
{if (a < b)return b;elsereturn a;
}
void print(int* data, int n)
{for (int i = 0; i < n; i++){cout << data[i] << " ";}cout << endl;
}
void HeadAdjust(int* data, int k, int n)//将以k为根的子树调整为大堆积根
{int tmp = data[k];int j ;if (2 * k + 2 < n){if (data[k] >= MAX(data[2 * k + 1], data[2 * k + 2]))//根结点大于其两个孩子结点{;}else if (data[2 * k + 1] > data[2 * k + 2])//左孩子结点的值大于右孩子结点{j = 2 * k + 1;swap(data[k], data[2 * k + 1]);for (int i = j; i < n; i = i * 2 + 1){HeadAdjust(data, i, n);}}else{j = 2 * k + 2;swap(data[k], data[2 * k + 2]);for (int i = j; i < n; i = i * 2 + 2){HeadAdjust(data, i, n);}}}else if (2 * k + 1 < n)//以k为根结点的时候,只有左孩子结点的时候{if (data[k] < data[2 * k + 1]){swap(data[k], data[2 * k + 1]);}}}void BulidHeap(int* data, int n)//建立大堆积树
{for (int i = (n - 2) / 2; i >= 0; i--)//(n-2)/2是树中第一个非叶子结点的下标{HeadAdjust(data, i, n);}
}
void HeadSort(int* data, int n)//基于大堆积树排序
{BulidHeap(data, n);//建立初始大堆积树//print(data, n);cout << "排序后:";for (int i = n - 1; i > 0; i--){cout << data[0] << " ";swap(data[0], data[i]);BulidHeap(data, i);//print(data, i);}cout << data[0];
}int main()
{int a[] = { 53,17,78,9,45,65,87,32 };cout << "排序前:";print(a, 8);BulidHeap(a, 8);cout << "建立的大堆积树:";print(a, 8);cout << endl;HeadSort(a, 8);return 0;
}

void HeadAdjust(int* data, int k, int len)//将以k为根的子树调整大根堆
{int tmp = data[k];//保存根结点int j = 2 * k;//下标为j的结点是下标为k的结点的左孩子while (j <= len){if (j < len && data[j] < data[j + 1])//右孩子较大,j指向右孩子{j++;//j变为2*i+1}if (data[k] < data[j]){data[k] = data[j];data[j] = tmp;k = j;//修改k和j的值,继续向下筛选j = 2 * k;}elsebreak;}
}
void HeapSort(int* data, int len)//堆排序
{for (int i = len / 2; i >= 1; i--)//循环建立初始堆{HeadAdjust(data, i, len);}for (int j = len; j >= 2; j--){swap(data[1], data[j]);HeadAdjust(data, 1, j-1);}
}
#include
#include
using namespace std;
void swap(int& a, int& b)//交换
{int tmp;tmp = a;a = b;b = tmp;
}
void HeadAdjust(int* data, int k, int len)//将以k为根的子树调整大根堆(data数组必须从1开始存放)
{int tmp = data[k];//保存根结点int j = 2 * k;//下标为j的结点是下标为k的结点的左孩子while (j <= len){if (j < len && data[j] < data[j + 1])//右孩子较大,j指向右孩子{j++;//j变为2*i+1}if (data[k] < data[j]){data[k] = data[j];data[j] = tmp;k = j;//修改k和j的值,继续向下筛选j = 2 * k;}elsebreak;}
}
void HeapSort(int* data, int len)//堆排序
{for (int i = len / 2; i >= 1; i--)//循环建立初始堆{HeadAdjust(data, i, len);}for (int j = len; j >= 2; j--){swap(data[1], data[j]);HeadAdjust(data, 1, j-1);}
}
void print(int* data, int n)
{for (int i = 1; i <= n; i++){cout << data[i] << " ";}cout << endl;
}
int main()
{//int a[] = { 53,17,78,9,45,65,87,32 };int a[100];int len;cout << "输入元素总数:";cin >> len;cout << "依次输入各个数据:";for (int i = 1; i <= len; i++){cin >> a[i];}cout << "排序前:";print(a, 8);HeapSort(a, 8);cout << "排序后:";print(a, 8);return 0;
}
归并排序

void Merge(int *data, int low, int mid, int high)//二路归并
{int* tmp = (int*)malloc((high - low + 2) * sizeof(int*));//辅助数组if (tmp==NULL){return;}int i = low, j = mid + 1, k = 0;while (i <= mid && j <= high)//在第一段和第二段均未扫描完时循环{if (data[i] <= data[j]){tmp[k++] = data[i++];//将前半段元素放入tmp[]数组中}else{tmp[k++] = data[j++];//将后半段元素放入tmp[]数组中}}while (i <= mid)//将前半段剩下元素复制到data[]数组中{tmp[k++] = data[i++];}while (j <= high)//将后半段剩下元素复制到data[]数组中{tmp[k++] = data[j++];}for (i = low, k = 0; i <= high; i++, k++){data[i] = tmp[k];//将tmp数组元素复制回data[]数组中cout << tmp[k] << " ";}cout << endl;free(tmp);
}void MergeSort(int *data, int low, int high)
{if (low < high){int mid = (low + high) / 2;MergeSort(data, low, mid); //对前半部分进行归并排序MergeSort(data, mid + 1, high);//对后半部分进行归并排序Merge(data, low, mid, high);//合并两段}
}
#include
#include
#include
using namespace std;
#define n 7//元素个数
void Merge(int *data, int low, int mid, int high)//二路归并
{int* tmp = (int*)malloc((high - low + 2) * sizeof(int*));//辅助数组if (tmp==NULL){return;}int i = low, j = mid + 1, k = 0;while (i <= mid && j <= high)//在第一段和第二段均未扫描完时循环{if (data[i] <= data[j]){tmp[k++] = data[i++];//将前半段元素放入tmp[]数组中}else{tmp[k++] = data[j++];//将后半段元素放入tmp[]数组中}}while (i <= mid)//将前半段剩下元素复制到data[]数组中{tmp[k++] = data[i++];}while (j <= high)//将后半段剩下元素复制到data[]数组中{tmp[k++] = data[j++];}for (i = low, k = 0; i <= high; i++, k++){data[i] = tmp[k];//将tmp数组元素复制回data[]数组中cout << tmp[k] << " ";}cout << endl;free(tmp);
}void MergeSort(int *data, int low, int high)
{if (low < high){int mid = (low + high) / 2;MergeSort(data, low, mid); //对前半部分进行归并排序MergeSort(data, mid + 1, high);//对后半部分进行归并排序Merge(data, low, mid, high);//合并两段}
}
void print(int* data)
{for (int i = 0; i < n; i++){cout << data[i] << " ";}cout << endl;
}
int main()
{int a[] = { 49,38,65,97,76,13,27 };MergeSort(a,0,n-1);print(a);return 0;
}
void Merge(int data[], int n)
{int* tmp = (int*)malloc(n * sizeof(int*));//辅助数组if (tmp == NULL){return;}int mid = (n - 1) / 2;int i = 0, j = mid+1, k = 0;while (i <= mid && j <= n-1)//在第一段和第二段均未扫描完时循环{if (data[i] <= data[j]){tmp[k++] = data[i++];//将前半段元素放入tmp[]数组中}else{tmp[k++] = data[j++];//将后半段元素放入tmp[]数组中}}while (i <= mid)//将前半段剩下元素复制到data[]数组中{tmp[k++] = data[i++];}while (j <= n-1)//将后半段剩下元素复制到data[]数组中{tmp[k++] = data[j++];}for (i = 0;i1){int mid = (n-1) / 2;MergeSort(data, mid+1); //对前半部分进行归并排序MergeSort(data+mid+1, n-(mid+1));//对后半部分进行归并排序(后半段起始位置元素下标是数组地址向后移动mid+1个位置)Merge(data, n);//合并两段}
}
#include
#include
#include
using namespace std;
void Merge(int data[], int n)
{int* tmp = (int*)malloc(n * sizeof(int*));//辅助数组if (tmp == NULL){return;}int mid = (n - 1) / 2;int i = 0, j = mid+1, k = 0;while (i <= mid && j <= n-1)//在第一段和第二段均未扫描完时循环{if (data[i] <= data[j]){tmp[k++] = data[i++];//将前半段元素放入tmp[]数组中}else{tmp[k++] = data[j++];//将后半段元素放入tmp[]数组中}}while (i <= mid)//将前半段剩下元素复制到data[]数组中{tmp[k++] = data[i++];}while (j <= n-1)//将后半段剩下元素复制到data[]数组中{tmp[k++] = data[j++];}for (i = 0;i1){int mid = (n-1) / 2;MergeSort(data, mid+1); //对前半部分进行归并排序MergeSort(data+mid+1, n-(mid+1));//对后半部分进行归并排序(后半段起始位置元素下标是数组地址向后移动mid+1个位置)Merge(data, n);//合并两段}
}
void print(int* data,int n)
{for (int i = 0; i < n; i++){cout << data[i] << " ";}cout << endl;
}
int main()
{int n = 7;//元素个数int a[] = { 49,38,65,97,76,13,27 };MergeSort(a, n);print(a,n);return 0;
}
基数排序
typedef int ElemType;
#define MAX 20//线性表最多的元素个数
#define MAXR 10//基数的最大取值
#define MAXD 8//关键字位数最大取值
typedef struct node
{char data[MAX];struct node* next;
}RecType;
void RadixSor(RecType*& p, int r, int d)//p存放待排序序列的单链表(无头结点),r为基数,d为关键字位数
{RecType* head[MAX], * tail[MAX],*t;int i, j, k;for (int i = d - 1; i >= 0; i--)//初始化各链队的首,尾指针{for (int j = 0; j < r; j++){head[j] = tail[j] = NULL;}while (p != NULL){k = p->data[i] - '0';//找第k个链队if (head[k] == NULL)//进行分配,尾插建单链表{head[k] = p;tail[k] = p;}else{tail[k]->next = p;tail[k] = p;}p = p->next;//取下一个待排序的元素}p = NULL;for (int j = 0; j < r; j++)//进行收集{if (head[j] != NULL){if (p == NULL){p = head[j];t = tail[j];}else{t->next = head[j];t = tail[j];}}}t->next = NULL;cout << "第" << i - d + 1 << "趟";print(p);}
}