最近正好複習複習演算法,於是從排序演算法開始做乙個總結。以下的**均為原創,如果有任何問題,歡迎指正。簡單來講,排序演算法的實質是將長度為n的陣列中的數字按照從小到大或者從大到小的順利排列。
簡而言之,在不考慮演算法的情況下,我們可以把排序抽象為如下的乙個函式:array表示t型別的乙個陣列,num表示陣列的長度。本文假設我們實現的排序演算法都是按照從小到大的順序排列;從大到小的排列類似。
template
void order(t array, int num)
1)選擇演算法:基本思想是每次從陣列中選擇最小的數,將這個數與已排序的陣列最後一位交換。尋找第乙個數時,我們需要遍歷num個數才能判斷出最小的數;尋找第i個數時,由於我們已經成功的將前i-1個數按序排列,我們只需要遍歷num-i+1個數便能找到最小的數。
總而言之,時間複雜度為o(n2),而空間複雜度為o(1)。
template void selectsort(t array, int num)
}//從未排序數種找出最小值
if(cur != i)
//如果最小值不是未排序數種的第乙個,則交換最小值與未排序數的第乙個。
}}
總而言之,時間複雜度為o(n2),而空間複雜度為o(1)。
template void ******insertsort(t array, int num)
else
}//手中的牌是有序的,於是每抽一張就一次往前比較。新牌比前面的牌小便往前移動直到手牌整理完成
}}
3)折半插入演算法:基本思想和簡單插入演算法相同,但是新牌與手牌比較的時候不必一一比較(因為手牌已經有序排列了),我們可以用二分查詢的方法來將新牌左移
總而言之,時間複雜度有所提高,為o(nlogn),而空間複雜度為o(1)。
template void binaryinsertsort(t array, int num)
else
};//利用二分法找到插入的位置
if(low != i)
array[low] = temp;
}//如果插入的位置與新牌的位置不同,則將新牌插入
}}
4)希爾排序:基本思想和簡單插入演算法類似。簡單插入演算法每一次從距離為一的位置處抽取新值。如果資料分布比較分散,簡單插入演算法效率較低。於是,我們可以採用距離(稱之為步長)大於一的方式來抽取新值。例如,當步長為n時,陣列中相當於有n個平行的子陣列在做簡單插入演算法。運算之後,陣列變得更加為有序,於是我們可以不斷地縮小步長直到步長為1(簡單插入演算法),最終完成排序。當陣列越有序時,簡單插入演算法的效率越高。
總而言之,時間複雜度不容易計算,但實驗統計結果大約為n1.25到1.6n1.25,而空間複雜度為o(1)。希爾是一種不穩定的演算法。
template void shellsort(t array, int num)}}
//步長為step的簡單插入演算法
}step = (step - 1) / 3;//縮短步長
}}
5)歸併排序:初始時,我們假設我們得到了num個長度為1的子陣列;每一次運算時將兩個有序的子陣列合併成乙個父陣列。
總而言之,時間複雜度為o(n2),而空間複雜度為o(n)。
template t minvalue(t a, t b)
//將數值臨時儲存在臨時儲存陣列中
merge(temparray, array, cur, m - 1, len);
//合併相鄰子陣列
cur += len * 2;
//指標指向下一組子陣列
};//依次選擇相鄰的子陣列合併
len *= 2;
cur = 0;
//長度翻倍且重置指標
};delete temparray;
}
6)氣泡排序:通過依次交換兩個相鄰的兩個數,遍歷num個數後便將最大的數推送到了最後。推送第乙個數時,我們需要遍歷num個數才能推出最大值;推送第i個數時,由於我們已經成功的將i-1個數按序推出,我們只需要遍歷num-i+1個數便能推出當前最大的數。
總而言之,時間複雜度為o(n2),而空間複雜度為o(1)。
template void bubblesort(t array, int num)
}//依次交換相鄰的數將最大值推送到陣列尾部已排序的陣列最前端
}}
7)快速排序:對氣泡排序法的優化,基本思想也是將兩個數交換,但是我們希望盡量將較小的數交換到陣列左邊,將交大的數交換到陣列右邊。計算時我們從陣列中隨機選擇乙個數作為參考數,定義乙個指標從左向右遍歷,另乙個指標從右向左遍歷。第乙個指標尋找大於參考數的數,第二個指標尋找小於參考數的數,並將兩個數交換。當兩個指標相遇時一次迴圈結束,迴圈結束時相遇位置的左側的數均小於參考數,右側的數均大於參考數。我們可以遞迴地對左側和右側的陣列運用快速排序演算法。
總而言之,時間複雜度為o(nlogn),而空間複雜度為o(1)。
template void quick(t array, int low, int high)
//長度小於10時採用簡單插入演算法
t key = array[low];//利用第乙個數作為參考數
int i = low;
int j = high;
while(true)
//兩個指標相遇時這次迴圈結束
t temp = array[i];
array[i] = array[j];
array[j] = temp;
//交換兩個指標的數
};if(i == j)
else
}//針對左側右側迴圈採用快速迴圈
}//快速排序
template void quicksort(t array, int num)
8)堆排序:堆就是一顆樹,分為最小化堆與最大化堆,最小化堆的特點是父節點大於等於子節點。堆的儲存可以利用數字完成,位置為0的節點表示更節點。對於父節點n,左右子節點為n*2+1與n*2+2。
對於乙個父節點兩個子節點的子堆,我們可以分成方便的轉化使父節點大於等於子節點。整個堆的整理便是迴圈遞迴計算。
總而言之,建堆時間複雜度為o(n),刪除、插入等操作時間複雜度為)(logn)。而空間複雜度為o(n)。
template class heap
;template heap::heap(t array, int num)
//初始化已有資料
for(int i = num; i < num * 2; i++)
//初始化預留資料
buildheap();
//建堆
}template heap::~heap()
template void heap::buildheap()
//從樹倒數第二層,葉節點的父節點向根節點迴圈,置換每個三節點子堆
}template void heap::switchheap(int n)
//如果較小值比父節點小,交換
switchheap(n * 2 + 1);
switchheap(n * 2 + 2);
//置換子節點中的子堆
}else if(n * 2 + 1 < len)//只包含左節點
//如果子節點比父節點小,交換
switchheap(n * 2 + 1);
//置換子節點中的子堆
}//沒有子節點不計算
}template t heap::pop()
template void heap::insert(t value)
else
}//沿著樹枝將最小值向根節點推送
}
排序演算法複習筆記
排序演算法一般都會有幾個較為基礎通用的方法,如下表 方法名作用 issorted 判斷陣列是否有序 less int item1,int item2 比較第乙個引數是否小於等於第二個引數 exch int a,int b 交換這兩個索引位置的元素 show 列印陣列 sort 具體待實現的排序演算法...
演算法導論 比較排序演算法筆記
好幾天沒看 演算法導論 今天看了一天的排序演算法,印象第一的是基數演算法,因為居然違反我的乙個常識,它採用的是最低有效位進行排序的。插入排序 歸併排序 堆排序 快速排序,這些都是比較排序演算法 它們都是通過對元素進行比較操作來確定輸入陣列的有序次序,這些演算法可以用決策樹模型分析,可以證明任意比較排...
排序演算法複習
參考自 直接插入排序 從小到大排列 n個資料,第乙個資料平凡有序 假設前i 1個資料串有序,根據第i個的大小將第i個插入到此串中,則前i個的資料串也有序。因此可得到n個資料有序。插入方法 待插入元素為第i元素,數值存為temp,將 i 之前的元素 j 從第 i 1 元素開始與之比較 如果比temp大...