//冒泡排序
//原理:从底部冒泡(逐个比较并进行交换),将最大(小)的元素顶到上面来.对已经排好序的就不再进行排序
//优化:对是否交换进行监视,如果没有发生交换,则已经排好序
static void PopSort(params int[] s)
{
int n = s.Length; //数组元素个数
//需要冒泡n-1次,因为最后一个元素显然已经排好序
for (int i = 1; i < n; i++)
{
//依次比较相邻元素->冒泡, 从底端冒泡
for (int j = n - 1; j >= i; j-- )
{
//可以增加一个bool标记,标记在比较中是否发生了交换,若没有发生交换则排序结束
if (s[j] < s[j-1]) //从小到大排序
{
//交换数据
int temp = s[j];
s[j] = s[j - 1];
s[j - 1] = temp;
}
}
}
}
//选择排序
//原理:每次选出最小(大)的元素,然后放在已经排好顺序的元素后面
static void SelectSort(params int[] s)
{
int n = s.Length;
for (int i = 0; i < n - 1; i++)
{
int small = i;
for (int j = i + 1; j < n; j++)
{
if (s[j] < s[small])
small = j;
}
//交换数据
int temp = s[small];
s[small] = s[i];
s[i] = temp;
}
}
//插入排序
//原理:将每一个元素与前面已经排好序的元素惊醒逐个比较,找到自己应该插入的位置(可以优化)
static void InsertSort(params int[] s)
{
int n = s.Length;
for (int i = 1; i < n; i++)
{
for (int j = i; j > 0; j--)
{
if (s[j] < s[j - 1])
{
//交换数据
int temp = s[j];
s[j] = s[j - 1];
s[j - 1] = temp;
}
else
break;
}
}
}
//快速排序
//原理:
//1.首先从待排序序列中任意选择一个记录k值作为轴值(privot)
//2.然后将剩余记录分割成两个子序列,L和R
//3.L在轴值左边,R在轴值右边
//4.对子序列L,R递归进行快速排序
//选择轴值:
//1.选第一个元素为轴值
//2.随机选择 缺点:需要额外的随机代码
//3.选择中间的元素 mid = (left+right)/2;
//分割序列:
//1.分别从序列的左端,右端向序列中间扫描,发现逆序就交换.直到已经扫描完整个序列,(需要对轴值做额外的处理)
//2.改进:不停的将逆序记录移动到空闲位置上,而不是直接交换逆序记录. 分割前先将轴值与最后一个记录交换,此时最后一个记录就是空闲位置
static void QuickSort(int left, int right, params int[] s)
{
if (right < left) //退出条件
return;
//应用分割序列方法2
//总是留出一个空闲位置来,最后这个空闲位置就是轴值的位置
int mid = (left + right) / 2;
int privot = s[mid]; //轴值
int temp = privot; //保存轴值
//交换轴值,将轴值放到最后一个位置上,因为有了轴值副本,所以最后一个位置变为了空闲位置
int t = s[right];
s[right] = s[mid];
s[mid] = t;
int i = left, j = right;
while (i != j) //i, j 未相遇呢
{
while ((s[i] < temp) && (j > i)) // j>i 此条件是必须的
i++;
if (i<j)
{
s[j] = s[i];
j--;
}
while ((s[j] > temp) && (j > i))
j--;
if (i < j)
{
s[i] = s[j];
i++;
}
}
s[i] = temp;
//对子序列进行排序
QuickSort(left, i - 1, s);
QuickSort(i + 1, right, s);
}