1. 程式人生 > >【資料結構】八大排序之氣泡排序

【資料結構】八大排序之氣泡排序

氣泡排序:(升序為例)

         利用兩個for迴圈每次比較相鄰的兩個元素,如果前一個元素比後一個元素大則交換兩個數。外層的for迴圈控制排序的總趟數,內層的for迴圈控制每一趟的相鄰兩個數的比較的次數

我們很輕易的看出:

      氣泡排序的時間複雜度最好情況為:

      氣泡排序的時間負責督最壞情況為

氣泡排序是穩定的排序

一.

下邊我們以陣列array[ ] = {5,8,6,3,9,2,1,7}為例,做升序排序

第一趟: 5 --> 8 --> 6 --> 3 --> 9 --> 2 --> 1 --> 7

               5 --> 6 --> 8 --> 3 --> 9 --> 2 --> 1 --> 7

               5 --> 6 --> 3 --> 8 --> 9 --> 2 --> 1 --> 7

               5 --> 6 --> 3 --> 8--> 2 --> 9 --> 1 --> 7  

               5 --> 6 --> 3 --> 8 --> 2 --> 1 --> 9 --> 7

               5 --> 6 --> 3 --> 8 --> 2 --> 1 --> 7 --> 9

第二躺: 5 --> 3 --> 6 --> 8 --> 2 --> 1 --> 7 --> 9

               5 --> 3 --> 6 --> 2 --> 8 --> 1 --> 7 --> 9

               5 --> 3 --> 6 --> 2 --> 1 --> 8 --> 7 --> 9

               5 --> 3 --> 6 --> 2 --> 1 --> 7 --> 8 --> 9

第三趟:

第四趟:

第五趟:

第六趟: 1 --> 2 --> 3 --> 5 --> 6 --> 7 --> 8 --> 9

第七躺:

第八躺:           

由於太多了,只能寫出少部分,和特殊的,其中沒寫的都是重複以上動作

程式碼展示:

void BubbleSort(int array[],int sz)
{

	for (int i = 0; i < sz; i++)
	{

		for (int j = 0; j < sz - i - 1 ; j++)
		{
			if (array[j] > array[j + 1])
			{
				int temp = 0;
				temp = array[j + 1];
				array[j + 1] = array[j];
				array[j] = temp;
				isSoretd = false;

			}
		}


	}
}

二.

               我們可以看出,當我們不假思索的寫出以上程式碼時,這個大部分人都可以搞定,這時候面試官肯定會問我們該去優化他

使得他效率更高。

            我們可以看到上面演示的過程中,在第六趟的時候,這個數組裡的資料已經是有序的了,然而我們還多餘的跑了兩趟,大大的降低了程式碼的效率

解決方法:

      我們可以利用特殊的函式來標記當資料已經是有序的就可以跳出迴圈。這時候我們就可以利用boolean(布林變數)isSorted作為標記。如果在本輪排序中沒有元素交換就證明資料已經有序,直接跳出迴圈。

       布林變數:

            是由兩種邏輯狀態的變數,他們分別為:true 和 false    常被用來作為標記

程式碼展示:

void BubbleSort(int array[],int sz)
{

	for (int i = 0; i < sz; i++)
	{
		boolean isSoretd = true;

		for (int j = 0; j < sz - i - 1 ; j++)
		{
			if (array[j] > array[j + 1])
			{
				int temp = 0;
				temp = array[j + 1];
				array[j + 1] = array[j];
				array[j] = temp;
				isSoretd = false;

			}
		}

		if (isSoretd)
		{
		break;
		}
	}
}

三.

這時候我們可以看到,程式碼在面對一些特殊情況時,效率上已經得到了極大的提升,但是這時候面試官可能覺得還不夠,我們還必須去進一步優化。

來看以下情況:(升序)

我們選定一個新的陣列 array[ ] ={3,4,2,1,5,6,7,8};

我們可以可到這個陣列內前半部分是無序的(3,4,2,1)但是後邊確實升序(5,6,7,8)

讓我們來看一下按照以前的方法排序過程:

第一趟:3 --> 4 --> 2 --> 1 --> 5 --> 6 --> 7 --> 8

              3 --> 2 --> 4 --> 1 --> 5 --> 6 --> 7 --> 8

              3 --> 2 --> 1 --> 4 --> 5 --> 6 --> 7 --> 8

             。。。。。。。。

第二趟:2 --> 3 --> 1 --> 4 --> 5 --> 6 --> 7 --> 8

              2 --> 1 --> 3 --> 4 --> 5 --> 6 --> 7 --> 8

第三趟:1 --> 2 --> 3 --> 4 --> 5 --> 6 --> 7 --> 8

      從上邊的過程我們可以看出,每趟的排序中在後邊是已經有序的資料,但是在每一輪的排序中還會去做無用功,這又一次大大的降低了程式執行的效率。

       我們可以看到影響效率的問題關鍵是:對數列有序區的界定

為了解決這個問題我們可以在沒一輪的迴圈中,記錄資料最後一次交換的位置,則這個就是數列的有序的邊界

程式碼展示:

void BubbleSort(int array[],int sz)
{

	//排序的最新邊界
	int sortborder = sz - 1;
	//記錄最後一次交換的位置
	int lastchange = 0;
	for (int i = 0; i < sz; i++)
	{
		boolean isSoretd = true;

		for (int j = 0; j < sortborder; j++)
		{
			if (array[j] > array[j + 1])
			{
				int temp = 0;
				temp = array[j + 1];
				array[j + 1] = array[j];
				array[j] = temp;
				isSoretd = false;

				lastchange = j;
			}
		}

		sortborder = lastchange;
		if (isSoretd)
		{
		break;
		}
	}
}

          以上就是本人自己想到的優化的地方,如果大家有什麼可以進一步優化的地方麻煩留言告訴我一聲,大家互相進步。