您的位置:首页 > 其它

【算法】 冒泡排序 & 快速排序

2016-05-29 14:59 232 查看



 冒泡排序(Bubble Sort)

    

1.算法原理

   

   从后向前,比较相邻的元素。如果第一个比第二个大,就交换他们两个。

   对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

   针对所有的元素重复以上的步骤,除了最后一个。

   持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

2.算法说明

       

       冒泡排序是一种比较简单的算法,但是第一次看还是觉得有些繁琐。

       它应用了双重嵌套循环,外面的循环是确定本次循环的范围,内部循环是在确定的范围里找到最大的数放到最前。

       这里涉及到有序序列和无序序列,简单来说,就是排好顺序的就是有序的,没排好的就是无序的。

       从它的工作机理来看就是“交换”,从最后那个数开始,和旁边的数比较大小,谁大谁往前,其实就是交换一下,然后就是倒数第二个和倒数三个比较,最后,这个数组的第一个数就是本数组最大的数,那么,我们的有序序列就有了一个数!就是最大那个数!

        这时候,外部循环进行了一次,内部循环整个循环一圈~

        然后外部循环的范围就会减1,其实它一直在确定无序序列的范围。然后内循环是找最大。

        总之,就这样,循环往复........

举个例子~

        如果有10个数,第一次从10个数中(外循环确定)找最大的数放在第一的位置(内循环整体循环一次可得到);

        第二次从9个数中(还是外循环确定的范围,第一个数已经是最大的了)找最大的数放在这9个数的第一的位置(内循环再次整体循环)

        就这样一直排下去....

 



 快速排序(Quick Sort)

1.算法原理

       

       设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

一趟快速排序的算法是:
       1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
       2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
       3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
       4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
       5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

2.算法说明

      

        快速排序是对冒泡排序的一种改进。

        冒泡排序通常不会使用,但是学习它可以帮助理解快速排序,那么快速排序到底改进了哪些???

        在冒泡排序中,我们是和旁边的数比较,然后让大数一步步的从后面换到前面,这样,未免有些笨,因为在日常生活中,如果我们给学生排队的话,肯定是让高个子的直接排到前面,低的排在后面,然后再微调,没人会让最高的那个一次一次的从后面“交换”上来,太慢了。。。

        所以,这里引入一个二分法的理念。

        简单来说,就是把大的放一块,小的放一块。然后继续划分,这样做的好处就是相比冒泡排序有种一步到位的感觉,因为它一下就把大数和小数分到差不多的位置,而不是笨笨的一点点移上去。



 代码对比

    

下面是冒泡排序和快速排序的代码(C#版)

static void Main(string[] args)
{

int numberCount;
int[] numbers;

Console.WriteLine("请问您要对多少个数字进行排序?");
numberCount = Convert.ToInt32(Console.ReadLine());

//生成指定数量的随机数
numbers = new int[numberCount];
System.Random rnd = new System.Random();
for (int i = 0; i < numberCount; i++)
{
numbers[i] = rnd.Next(1, numberCount); ;
}
Console.WriteLine();

//冒泡排序
System.Diagnostics.Stopwatch watch1 = new System.Diagnostics.Stopwatch();
watch1.Start();
for (int i = 0; i < numbers.Length - 1; i++)
{
for (int j = 0; j < numbers.Length - 1 - i; j++)
{
if (numbers[j] > numbers[j + 1])
{
int temp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = temp;
}
}
}
watch1.Stop();
Console.WriteLine("冒泡排序 耗费时间为: {0} 毫秒", watch1.ElapsedMilliseconds);
Console.WriteLine();

//快速排序
System.Diagnostics.Stopwatch watch5 = new System.Diagnostics.Stopwatch();
watch5.Start();
sort(numbers, 0, numbers.Length - 1);
watch5.Stop();
Console.WriteLine("快速排序 耗费时间为: {0} 毫秒", watch5.ElapsedMilliseconds);
Console.WriteLine();

Console.ReadKey();
}

private static int sortUnit(int[] array, int low, int high)
{
int key = array[low];
while (low < high)
{
/*从后向前搜索比key小的值*/
while (array[high] >= key && high > low)
--high;
/*比key小的放左边*/
array[low] = array[high];
/*从前向后搜索比key大的值,比key大的放右边*/
while (array[low] <= key && high > low)
++low;
/*比key大的放右边*/
array[high] = array[low];
}
/*左边都比key小,右边都比key大。//将key放在游标当前位置。//此时low等于high */
array[low] = key;
return high;
}

public static void sort(int[] array, int low, int high)
{

if (low >= high)
return;
/*完成一次单元排序*/
int index = sortUnit(array, low, high);
/*对左边单元进行排序*/
sort(array, low, index - 1);
/*对右边单元进行排序*/
sort(array, index + 1, high);
}
}


输入的结果为:





 空间复杂度 & 时间复杂度

    



   

       在这里要涉及到空间复杂度和时间复杂度的问题,简单来说就是需要多少内存来处理和需要多少时间来处理。

       通常情况下,降低空间复杂度会引起时间复杂度的上升。其实这也很好理解,同样的任务量,人少时间用的就多,人多时间用的就少。当然,这也不是绝对的,如果你的方法上升到更高的维度,说不定你所用的空间和时间都会减少。



 总结

    

      对算法的研究还会继续进行下去,他们可以很好帮助我们优化我们的代码。

      这些凝结的智慧会对我们有很大启发,站在巨人之上,学习并超越。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: