1.冒泡排序
- 算法步骤
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
2.代码
void Bubble_Sort(int *num, int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (num[j] < num[j+1])//后面的大于前面的交换
{
int temp = num[j];
num[j] = num[j+1];
num[j+1] = temp;
}
}
}
}
2.选择排序
- 算法步骤
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
重复第二步,直到所有元素均排序完毕。
2.代码
void Selsction_Sort(int *num, int n)
{
for (int i = 0; i < n; i++)
{
int k = i;//记录选择位置
for (int j = i; j < n; j++)
{
//后面位置上的元素大于选择位置上的元素更改记录位置
if (num[k] < num[j])
{
k = j;
}
}
if (k != i)//交换记录位置和选择位置
{
int temp = num[k];
num[k] = num[i];
num[i] = temp;
}
}
}
3.插入排序
-
算法步骤
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
void Insertion_Sort(int *num, int n)
{
//注意数组超限问题
for (int i = 1; i < n; i++)
{
int k = num[i],j = i;
for (; j > 0; j--)
{
if (k > num[j-1])//与当前位置的前一个位置比较
{
num[j] = num[j-1];
}
else
break;
}
//此时j指向0位置
num[j] = k;
}
}
4.希尔排序
- 算法步骤
选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
按增量序列个数 k,对序列进行 k 趟排序;
每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
2.代码
void Shell_Sort(int *num, int n)
{
int gap = 1;
while (gap * 3 + 1 < n)//尽可能大的分组
gap = gap * 3 + 1;
while (gap > 0)
{
for (int i = 0; i < gap; i++)//循环次数
{
//使用插入排序方法
for (int j = i + gap; j < n; j += gap)
{
int t = j, k = num[j];
for (; t>=gap; t -= gap)//注意这层循环的结束位置
{
if (k > num[t - gap])
{
num[t] = num[t - gap];
}
else
break;
}
num[t] = k;
}
}
gap = (gap - 1) / 3;
}
}
5,快速排序
- 算法步骤
从数列中挑出一个元素,称为 “基准”(pivot);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序; - 代码
int Quick_Sort(int *num, int n, int left, int right)
{
//退出条件
if (left >= right || left > n - 1 || right > n - 1 || right <= 0 || left<0)
{
return -1;
}
int base = num[left];
while (left != right)
{
while (num[right] < base && right > left) right--;
num[left] = num[right];
while (num[left] > base && right > left) left++;
num[right] = num[left];
}
num[left] = base;
return left;
}
void Quick_Sort_Re(int *num, int n, int left, int right)
{
if (left >= right || left > n - 1 || right > n - 1 || right <= 0 || left<0)
{
return;
}
int baseid = Quick_Sort(num, n, left, right);
if (baseid != -1)
{
Quick_Sort_Re(num, n, left, baseid - 1);
Quick_Sort_Re(num, n, baseid + 1, right);
}
}
6.归并排序
- 算法步骤
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
设定两个指针,最初位置分别为两个已经排序序列的起始位置;
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
重复步骤 3 直到某一指针达到序列尾;
将另一序列剩下的所有元素直接复制到合并序列尾。
2.代码
void Merge_Sort(int *num, int *arr, int first, int last)//合并
{
int mid = (last - first) / 2 + first;
int i = first, j = mid + 1,k=0;
while (i <= mid && j <= last)
arr[k++] = num[i] > num[j] ? num[i++] : num[j++];
while (i <= mid)
arr[k++] = num[i++];
while (j <= last)
arr[k++] = num[j++];
for (int m = 0; m < k; m++)
{
num[m + first] = arr[m];
}
}
void Merge_Sort_Re(int *num, int *arr, int first, int last)//拆分
{
if (first >= last)
return;
int mid = (last - first) / 2 + first;
Merge_Sort_Re(num, arr, first, mid);
Merge_Sort_Re(num, arr, mid+1, last);
Merge_Sort(num, arr, first, last);
}
7.堆排序
- 算法步骤
创建一个堆 H[0……n-1];
把堆首(最大值)和堆尾互换;
把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
重复步骤 2,直到堆的尺寸为 1。
2.代码
void Heap_Sort_Node(int *num, int n, int node)//调整节点
{
if (2 * node + 1 > n - 1)
return;
int index = 0;
if (2 * node + 2 > n - 1)
index = 2 * node + 1;
else
index = num[2 * node + 1] < num[2 * node + 2] ? (2 * node + 1) : (2 * node + 2);
if (num[index] < num[node])
{
int temp = num[node];
num[node] = num[index];
num[index] = temp;
Heap_Sort_Node(num,n,index);
}
}
void Heap_Sort(int *num, int n)
{
return;
//第一次堆调整节点将每个节点下的子节点都比父节点大
for (int i = n / 2 - 1; i >= 0; i--)
Heap_Sort_Node(num, n, i);
//交换头尾
swap(num[0], num[n - 1]);
int qun = n - 1;
while (qun)
{
Heap_Sort_Node(num, qun, 0);
swap(num[0], num[qun-1]);
qun--;
}
}
8.基数排序
- 基数排序
基数排序有两种方法:
这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:
基数排序:根据键值的每位数字来分配桶;
计数排序:每个桶只存储单一键值;
桶排序:每个桶存储一定范围的数值;
2.代码
int GetMax(int* num)
{
int temp = num[0];
for (int i = 0; i < 10;i++)
{
if (temp < num[i])
{
temp = num[i];
}
}
return temp;
}
void radix(int *num, int exp)
{
int temp[10];
int temp2[10] = { 0 };
//1.统计位数上数据出现次数
for (int i = 0; i < 10; i++)
{
temp2[(num[i] / exp) % 10]++;
}
//2.改变temp2使其数据成为排序后的位置..决定升序或降序
for (int i = 1; i <10; i++)
{
temp2[i] += temp2[i - 1];
}
//3.放入临时的数组里面
for (int i = 9; i >= 0; i--)
{
temp[temp2[(num[i] / exp)%10] - 1] = num[i];
temp2[(num[i] / exp) %10]--;
}
//4.复制num中
for (int i = 0; i < 10; i++)
{
num[i] = temp[i];
}
}
int main()
{
int num[10] = { 10, 15, 1, 2, 4, 25, 100, 50, 9, 6 };
//1.得到最大值
int Max = GetMax(num);
//2.定义指数控制循次数以及每次的位数
for (int exp = 1; Max / exp > 0; exp *= 10)
{
radix(num, exp);
}
//输出
for (int n : num)
{
cout << n << endl;
}
return 0;
}