冒泡排序算法顧名思義,通過每一次排序算法以後,最大的泡泡(數)會飄到最上面,第二次排序以後,第二大的泡泡(數)飄到倒數第二的位置 ..... 以此類推,直至完成從小到大的排序。算法
冒泡排序原理:優化
- 比較相鄰的元素。若是第一個比第二個大,就交換他們兩個。
- 對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對。這步作完後,最後的元素會是最大的數。
- 針對全部的元素重複以上的步驟,除了最後一個。
- 持續每次對愈來愈少的元素重複上面的步驟,直到沒有任何一對數字須要比較。
用圖片表示冒泡排序的過程更直觀:code
依照冒泡排序的概念能夠方便的寫出排序的實現:排序
- (void)bubbleSort:(NSMutableArray *)arr { int count = 0; int cycleCount = 0; for (int i = 0; i<arr.count-1; i++) { cycleCount += 1; // 每次循環都不須要比較最後一個,倒數第二個,倒數第三個... 因此二層循環最好減去已經排好序的數 for (int j = 0; j<arr.count-i-1; j++) { cycleCount += 1; if ([arr[j] integerValue] > [arr[j+1] integerValue]) { NSInteger temp = [arr[j] integerValue]; arr[j] = arr[j+1]; arr[j+1] = @(temp); count += 1; } } } NSLog(@"交換次數-->%@",@(count)); NSLog(@"循環次數-->%@",@(cycleCount)); NSLog(@"%@",arr); }
上面的方式是最原始的排序,再次基礎上能夠對冒泡排序進行優化 。圖片
冒泡排序的主要操做就是不斷的循環比較而後交換兩個大小不一樣的數的位置。 若是要正確的排序交換的次數確定是固定的,這個是不能減小的,那就從循環比較上進行優化 。 table
用一個變量進行記錄,記錄在一次循環中是否發生了交換,若是沒有則說明這個序列已是有序的了,則退出循環。class
- (void)bubbleSort:(NSMutableArray *)arr { int count = 0; int cycleCount = 0; for (int i = 0; i<arr.count-1; i++) { cycleCount += 1; finished = YES; for (int j = 0; j<arr.count-i-1; j++) { cycleCount += 1; if ([arr[j] integerValue] > [arr[j+1] integerValue]) { NSInteger temp = [arr[j] integerValue]; arr[j] = arr[j+1]; arr[j+1] = @(temp); finished = NO; count += 1; } } if (finished) break; } NSLog(@"----交換次數爲%@",@(count)); NSLog(@"----循環次數爲%@",@(cycleCount)); NSLog(@"%@",arr); }
仔細研究冒泡排序的原理能夠發現,還能夠再次基礎上進行優化。 記錄每一次內層循環排序最後發生位置交換的位置K,這個位置以後的都已是有序的了,下次排序內層循環只須要排序前 0--K 個數便可 。基礎
- (void)bubbleSort3:(NSMutableArray *)arr { int count = 0; int cycleCount = 0; int pos = (int)arr.count-1; for (int i = 0; i<arr.count-1; i++) { finished = YES; cycleCount += 1; int currentPos = 0; // 從上一次發生交換的位置開始循環 for (int j = 0; j<pos; j++) { cycleCount += 1; if ([arr[j] integerValue] > [arr[j+1] integerValue]) { NSInteger temp = [arr[j] integerValue]; arr[j] = arr[j+1]; arr[j+1] = @(temp); count += 1; // 記錄發生交換的位置 currentPos = j; finished = NO; } } pos = currentPos; if (finished) break; } NSLog(@"交換次數-->%@",@(count)); NSLog(@"循環次數-->%@",@(cycleCount)); NSLog(@"%@",arr); }
時間複雜度:變量
冒泡排序須要進行兩層循環,最壞的狀況是:序列正好是倒序的,這種狀況是O(n²),最好的狀況是:序列正好的是正序的,這種狀況是:O(n) .平均時間複雜度是O(n²)。原理
因爲時間複雜度是平方級的,因此冒泡排序通常適用於小序列排序 。序列小(如:長度在20個之內)的狀況下冒泡排序是比快排的速度還要快的。