冒泡排序
冒泡排序的基本思想:通過無序區中相鄰記錄關鍵字間的比較和位置的交換,使關鍵字最小的記錄如氣泡一般逐漸往上“漂浮”直至“水面”。
整個算法是從最下面的記錄開始,對每兩個相鄰的關鍵字進行比較,且使關鍵字較小的記錄換至關鍵字較大的記錄之上,使得經過一趟冒泡排序後,關鍵字最小的記錄到達最上端,接着再在剩下的記錄中找關鍵字次小的記錄,並把它換在第二個位置上。依次類推,一直到所有記錄都有序爲止。
**若有 n個數據元素,則比較次數爲:(n-1)n/2
交換次數:
如果序列本身有序,無需交換
如果序列本身倒序,交換(n-1)n/2
因此,冒泡排序的時間複雜度爲O(n^2)
2)穩定性
#include "stdafx.h"
#include<iostream>
#include<string>
using namespace std;
// 冒泡排序
int main()
{
int list[10] = { 56,98,10,84,19, 53,68,73,34,71 };
int length = sizeof(list) / sizeof(list[0]);//求數組長度
cout << length << endl;
//-----------------------------------------------
for (int i = 0; i < length-1; i++)
{
for (int j = 0; j < length-1-i; j++)
{
if (list[j]>list[j+1])
{
int temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
}
}
}
for (int i = 0; i < length; i++)
{
cout << list[i]<<" ";
}
return 0;
}
插入排序
假設待排序的記錄存放在數組R[0…n-1]中,排序過程的某一中間時刻,R被劃分成兩個子區間R[0…i-1]和R[i…n-1],其中:前一個子區間是已排好序的有序區,後一個子區間則是當前未排序的部分,不妨稱其爲無序區。
直接插入排序的基本操作是將當前無序區的第1個記錄R[i]插入到有序區R[0…i-1]中適當的位置上,使R[0…i]變爲新的有序區。
**1)時間複雜度
若有 n個數據元素序列
如果序列本身有序,比較n-1次,交換0次
如果序列本身倒序,比較(n-1)n/2次,交換(n-1)n/2次
所以插入排序的時間複雜度爲O(n2),最優複雜度爲O(n)
2)穩定性
#include "stdafx.h"
#include<iostream>
#include<string>
using namespace std;
int main()
{
int list[10] = { 56,98,10,84,19, 53,68,73,34,71 };
int length = sizeof(list) / sizeof(list[0]);//求數組長度
cout << length << endl;
int key = 0;//監視哨
for (int i = 0; i < length; i++)
{
for (int j = i-1; j >=0; j--) //******
{
if (list[j+1]>list[j])
{
key = list[j + 1];
list[j + 1] = list[j];
list[j] = key;
}
}
}
for (int i = 0; i < length; i++)
{
cout << list[i] << " ";
}
return 0;
}
希爾 排序
希爾排序:希爾排序又稱爲縮小增量排序,它是一種插入排序。其基本思想是:
把記錄按步長(增量)分組,對每組記錄採用插入排序方法進行排序;
隨着步長逐漸縮小,所分成的組包含的記錄越來越多,當步長的值減到1時,整個數據合成爲一組;
增量序列的選擇一般依據下面兩點:
1)最後一個增量必須爲1;
2)應該儘量避免序列中的值(尤其是相鄰的值)互爲倍數的情況。
希爾排序的時間性能優於直接插入排序的原因:
1)當數據有序時,插入排序所需的比較和移動次數均較少,複雜度爲O(n)。
2)在希爾排序分組,每組的記錄數目少,使用插入排序速度快,當增量爲1時,數據又接近有序,速度自然快了。因此,希爾排序在效率上較直接插人排序有較大的改進。平均時間複雜度爲O(n^2)。
因爲以增量跳躍分組排序,所以希爾排序不穩定。
#include <iostream>
#include<string>
using namespace std;
/*數組遍歷*/
void ListShow(int list[],int length){
for(int i=0;i<10;i++){
cout<<list[i]<<" ";
}
cout<<endl;
}
void ShellSort(int *list,int len){
int incream=len;//增量
int i,j;
int key=0;
do{
incream=incream/3;
for(i=incream;i<len;i++){
if(list[i]<list[i-incream]){
key=list[i];
for(j=i-incream;j>=0&&key<list[j];j-=incream){
list[j+incream]=list[j];
list[j]=key;
}
}
}
}while(incream>1); cout<<"結果:";
ListShow(list,len);
}
int main()
{
int list[10]={56,98,10,84,19, 53,68,73,34,71};
int length=sizeof(list)/sizeof(list[0]);//求數組的長度,C++固定方式
ListShow(list,length);
ShellSort(list,length);
return 0;
}
快速排序
快速排序的基本思想:在待排序的n個記錄中任取一個記錄,把該記錄放入適當位置後,數據序列被此記錄劃分成兩部分。所有關鍵字比該記錄關鍵字小的記錄放置在前一部分,所有比它大的記錄放置在後一部分,並把該記錄排在這兩部分的中間(稱爲該記錄歸位),這個過程稱作一趟快速排序。 首先對無序的記錄序列進行“一次劃分”,之後分別對分割所得兩個子序列“遞歸”進行快速排序。
設待排序的表有10個記錄,其關鍵字分別爲{6,8,7,9,0,1,3,2,4,5},採用快速排序方法進行排序的詳細過程如下圖所示。
排序步驟:
1**)選取6爲key,先從尾部(high指針)開始查找比key小的數與key交換,然後從頭部(low指針)開始查找比key大的數與key交換,交替進行,直到high指針和low指針相遇,第一趟排序結束,由key將序列分成左右兩個子序列,左邊都比key小,右邊都比key大。
2)以同樣的方法排序左子序列,直到左子序列有序。
3)再以同樣的方法排序右子序列,直到右子序列有序。**
)時間複雜度
現有 n個數據元素序列
首先對整個數列所有元素都比較一次,分成兩個序列,比較的次數爲n
然後再對這兩個子序列排序,假設子序列時間排序爲O(n/2)
則n個元素的時間複雜度=
<=2O(n/2)+n
<=2(2(O(n/4))+n/2))+n=4O(n/4)+2n
<=2(2(2(O(n/8))+n/4)+n/2))+n=8O(n/8)+3n
……
<=n(O(1))+nlog2^n (O(1)=0)
<= nlog2^n
快速排序的時間複雜度爲:O(nlog2^n)
2)穩定性
在實施快速排序的過程中,相同元素的順序過能會因爲在左右兩個序中不斷的改變位置,因此最後的排序結果相同元素的位置有可能發生變化,因此快速排序算法是不穩定的。