目录
冒泡排序基本思想(默认从小到大):
每轮比较相邻的两个数进行交换操作,每一轮完毕,无序集里最大的数都会排在有续集里。
若每轮从左到右进行比较,则有续集在右边,每轮的最大数在右边有序集中冒泡。
若每轮从右到左进行比较,则有续集在左边,每轮的zuix最小数在左边有序集中冒泡。
与选择排序不同,选择排序初始最左边最小,在剩下的里面逐个比较选择选择更小的替换此位置上的值,知道一轮完毕,选出最小的替换在最左边。如此进行第二轮。冒泡排序则每一轮进行相邻的数比较排序,最大的数逐渐被替换到最右边,得到第一轮有序集,如此进行第二轮。
版本1 基本的冒泡排序
没有任何优化,eg 5 6 7 3 9 2 1 8
6轮之后 1 2 3 4 5 6 7 8后面两轮在做无用功
//冒泡排序 时间复杂度仍未n^2但是有效
void BubbleSortV1(int arrey[], int len)//顺序比较,顺序集合在后
{
int temp;
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len - i -1; j++)//有序集长度为i即比较的轮数,有序集没必要比较
{
if (arrey[j] > arrey[j+1])
{
temp = arrey[j];
arrey[j] = arrey[j+1];
arrey[j+1] = temp;
}
}
}
}
版本2:纵向优化(通过标记是否交换,减少不必要的比较轮数)
通过引入exchange标记每一轮是否发生交换,若发生交换则说明并未排好序,继续下一轮,否则排好序退出循环。
//冒泡排序 exchange 标记优化 时间复杂度仍未n^2但是有效
void BubbleSortV2(int arrey[], int len)//顺序比较,顺序集合在后
{
int temp;
int exchange = 1;//交换标记 0 没发生交换集合已经顺序 否则发生交换排序未完成
for (int i = 0; i < len&&exchange ==1; i++)
{
exchange = 0;//每一趟默认排序好 若此趟已经排序好 则下一趟exchange 为0排序结束循环结束
for (int j = 0; j < len - i -1; j++)//有序集长度为i即比较的轮数,有序集没必要比较
{
if (arrey[j] > arrey[j+1])
{
temp = arrey[j];
arrey[j] = arrey[j+1];
arrey[j+1] = temp;
exchange = 1;//发生交换
}
}
}
}
V3 横向优化(优化有序集,用实际有续集减少不必要的比较)
//优化Bubble,实际中有序集长度可能大于算法有序集
//eg 3 2 1 4 5 6 7 8 第一轮比较算法有序集为0,但第一轮比较两次之后
//是 3 2交换后 2 1交换 2 1 3 4 5 6 7 8 3后面已经是实际有序,但算法有续集为0
//故后面得比较5次无用的
//优化 记录最后一次交换的位置即为实际的有序集Border
void BubbleSortV3(int arrey[], int len)
{
int tmp = 0;
int lastexIndex = 0;
int Border = len - 1;
int exchange = 1;
for (int i = 0; i < len && (exchange); i++)
{
exchange = 0;//每一轮默认不交换 证明排序好 若此轮已经排序好 则下一轮exchange 为0排序结束循环结束
for (int j = 0; j < Border; j++)
{
if (arrey[j] > arrey[j + 1])
{
tmp = arrey[j];
arrey[j] = arrey[j + 1];
arrey[j + 1] = tmp;
exchange = 1;
lastexIndex = j;//记录实际有序集的边界,即最后一次交换的j
}
}
Border = lastexIndex;//记录最后发生交换的位置,即实际有序集边界
}
}
v4 鸡尾酒法(左右比较优化以下情况)
//2 3 4 5 6 7 1 8
//若按照之前的排序方法从左到右 得8轮排序但是只有1位置不对
//从右到左排序只需要1轮
//通用性:先从左到右在从右到左,则可以避免这种问题 需要两个边界,两轮
//鸡尾酒排序
void BubbleSortV4(int arrey[], int len)
{
int tmp = 0;
int lastexLeftIndex = 0;
int lastexRightIndex = 0;
int BorderLeft = 0;
int BorderRight = len - 1;
int exchange = 1;
for (int i = 0; i < len/2 -1 && (exchange); i++)//每一轮进行左右冒泡则每轮有序集增加2个,轮次减半
{
exchange = 0;//每一轮默认不交换 证明排序好 若此轮已经排序好 则下一轮exchange 为0排序结束循环结束
//奇数轮次 从左到右 左右都有有序集故左边起始为i(有序集边界) BorderLeft
for (int j = BorderLeft; j < BorderRight; j++)
{
if (arrey[j] > arrey[j + 1])
{
tmp = arrey[j];
arrey[j] = arrey[j + 1];
arrey[j + 1] = tmp;
exchange = 1;
lastexRightIndex = j;//记录实际有序集的边界,即最后一次交换的j
}
}
BorderRight = lastexRightIndex;//记录最后发生交换的位置,即实际有序集边界
//偶数轮次 从右到左 左右都有有序集故右边起始为j(有序集边界)BorderRight
for (int j = BorderRight; j >BorderLeft ; j--)
{
if (arrey[j] < arrey[j - 1])
{
tmp = arrey[j];
arrey[j] = arrey[j - 1];
arrey[j - 1] = tmp;
exchange = 1;
lastexLeftIndex = j;//记录实际有序集的边界,即最后一次交换的j
}
}
BorderLeft = lastexRightIndex;//记录最后发生交换的位置,即实际有序集边界
}
}
好困啊,昨晚实验室任务阶段性完成,如释重负,农药打到晚上3点,上个钻石(菜鸟级别)哎,早上起不来,标记以下,希望后面能够自律一点。