原寫(xiě)作時(shí)間 | 2013-03-27 |
---|
關(guān)于排序的算法有很多。作為初學(xué)者。我在掌握了冒泡排序后掌握的第二個(gè)排序算法是插入排序。一個(gè)多月前看了一些資料,了解了排序的思想,然后自己摸索出了代碼的寫(xiě)法。并一直這樣寫(xiě)了這么久。直到今天看了《算法導(dǎo)論》的時(shí)候,才恍然大悟,原來(lái)自己一直寫(xiě)的插入排序并不十分正確。雖然思想是相通的。但是運(yùn)行的效率卻相差很多。
比如一個(gè)數(shù)列。用數(shù)組表示。a[n]。
我寫(xiě)的插入排序是這樣
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
for(j=0;j<i;j++)
{
if(a[i]<a[j])
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
這樣寫(xiě)是一種邊初始化賦值編排序的寫(xiě)法。如果是處理一段已經(jīng)序列。則直接寫(xiě)成
for(i=1;i<n;i++)
for(j=0;j<i;j++)
{
if(a[i]<a[j])
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
//以上兩種方法第二個(gè)for語(yǔ)句也可以改成
for(j-i-1;j>=0;j--)
{
if(a[i]<a[j])
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
看到這里你會(huì)發(fā)現(xiàn)這里也是用的插入排序的思想。只不過(guò)關(guān)鍵是在插入的處理上。我的算法比正統(tǒng)算法差了好多。大家都知道計(jì)算機(jī)的數(shù)據(jù)插入無(wú)法直接像加、減、乘、除、賦值那樣一步到位。正規(guī)的寫(xiě)法是:
for(i=1;i<n;i++)
t=a[i];
for(j=i-1;j>0;j--)
{
if(a[j]>t)
a[j+1]=a[j];
}
a[i+1]=t;
假設(shè)一次賦值運(yùn)算的時(shí)間為1,然后在最壞的情況,逆序的時(shí)候,我原來(lái)的寫(xiě)法需要移動(dòng)的次數(shù)分別為1、2、3……n-1。一共是n*(n-1)/2
次。每次移動(dòng)實(shí)際是三次賦值運(yùn)算,時(shí)間為3倍n*(n-1)/2
。而正規(guī)的的寫(xiě)法移動(dòng)次數(shù)分別是1、2、3、……n-1每次移動(dòng)做一次賦值運(yùn)算。最后的“插入”也是一次賦值。所以時(shí)間一共是n*(n-1)/2
。所以我原來(lái)的寫(xiě)法效率與之相差太多啦。
怎么樣,同樣的思想(額,其實(shí)是不完全相同),寫(xiě)出來(lái)的程序效率還是不同的。【以上內(nèi)容倉(cāng)促寫(xiě)就,或有訛誤。】
關(guān)鍵點(diǎn)在于兩者在于“插入”方法的處理上。我有這樣一種設(shè)想,就是用鏈表的方式存儲(chǔ)元素。插入的時(shí)候直接修改指針。時(shí)間效率或許會(huì)有提高。我也沒(méi)驗(yàn)證。不過(guò)即使我的設(shè)想是正確的,可以肯定的是那將是一種犧牲空間的時(shí)間優(yōu)化法。
后記 | 2017-09-13 |
---|
現(xiàn)在看來(lái)當(dāng)時(shí)寫(xiě)的分析比較拙劣。實(shí)際時(shí)間復(fù)雜度中的常數(shù)系數(shù)的大小是基本可以忽略的。