[7] 演算法之路,演算法之路
左軸演算、中軸演算、右軸演算
題目:
快速排序法(quick sort)是目前所公認最快的排序方法之一(視解題的對象而定),雖然快速排序法在最差狀況下可以達O(n2),但是在多數的情況下,快速排序法的效率表現是相當不錯的。
快速排序 - 演算法
1、快速排序法的基本精神是在數列中找出適當的軸心,然後將數列一分為二
2、分別對左邊與右邊數列進行排序
左軸演算:
// 快速排序 - 左軸演算// 1. 附設兩個指標left/right,並設最左端的數為最初樞軸pivot// 2. 從右向左搜尋,找到第一個比pivot小的數,將其緩衝進樞軸位置// 3. 從左向右搜尋,找到第一個比pivot大的數,緩衝進上一個比pivot小的數的位置程式進入2.迴圈// 4. 最後一次交換後獲得的有效空位置為a[i] ,此時再將pivot賦值給a[i] 此時a[i]左邊的數比a[i]小,右邊的數比a[i]大// 再分別對其左邊與左邊進行快速排序int QuickSort2(int a[],int left,int right){if(left<right){int i = left,j=right,pivotloc=a[left];while(i < j){while(i<j && a[j]>=pivotloc) j--;if(i<j) a[i++]=a[j];while(i<j && a[i]<pivotloc)i++;if(i<j) a[j--]=a[i];}a[i]=pivotloc;QuickSort2(a,left,i-1);QuickSort2(a,i+1,right);}return 0;}
int QuickSort5(int a[],int left,int right){if(left<right){int i = left,j=right,pivotloc=a[left];while(i < j){while(i<j && a[i]<=pivotloc) i++;while(i<j && a[j]>pivotloc) j--;if(i<j){SWAPER(a[i],a[j]);i++;j--;}}if(a[j]<a[left]) {SWAPER(a[left],a[j]);}QuickSort5(a,left,j-1);QuickSort5(a,j,right);}return 0;}
中軸演算
// 快速排序int QuickSort3(int a[],int left,int right){int i,j,pivot;if(left<right){pivot=a[(left+right)/2];i=left-1;j=right+1;while(i<j){while(a[++i]<pivot) ;while(a[--j]>pivot) ;if(i<j) SWAPER(a[i],a[j]);}QuickSort3(a,left,i-1);QuickSort3(a,j+1,right);}return 0;}
右軸演算
// 快速排序演算// 1. 首先選擇最右邊的元素作為樞軸pivot// 2. 從左向右搜尋,尋找小於pivot的數,將其與左邊第一個未交換的元素交換// 3. 當搜尋到最右邊時,左邊已交換的數都比pivot小,而未交換的都比pivot大// 4. 將左邊的第一個未交換的元素與最右邊的pivot元素交換,並返回該未交換元素的索引// 此時i左邊的元素比i小,右邊的比i大// 程式進入.迴圈分別對0 →i -1 及最右邊的i+1→right進行遞迴(快速排序) 最終該序列會變為有序int Partition2(int a[],int left,int right){int i = left,j;int pivot=a[right];for(j=left;j<right;j++){if(a[j]<pivot){if(i!=j)SWAPER(a[i],a[j]);i++;}}if(i!=right)SWAPER(a[i],a[right]);return i;} int QuickSort4(int a[],int left,int right){int pivot;if(left<right){pivot=Partition2(a,left,right);QuickSort4(a,left,pivot-1);QuickSort4(a,pivot+1,right);}return 0;}
MATLAB的迪傑斯特拉演算法7個起始點到15個終點的最短路徑
你對圖論的知識有瞭解吧~W是關聯矩陣,s和t分別是起始點和終止節點的序號。返回的d為最短的加權路徑長度,p為最優路徑節點的序號向量。注意,這裡W矩陣為0的點權值已經自動設為無窮大了。請參考《高等應用數學問題的 MATLAB一書》。我吧程式賦給你。
你做一個M函數用吧。
function [d,path]=dijkstra(W,s,t)
[n,m]=size(W);ix=(W==0);W(ix)=inf;
if n~=m,error('Square W required');end
visited(1:n)=0; dist(1:n)=inf;parent(1:n)=0;dist(s)=0;d=inf;
for i=1:(n-1),%求出每個節點與起始點的關係
ix=(visited==0);vec(1:n)=inf;vec(ix)=dist(ix);
[a,u]=min(vec);visited(u)=1;
for v=1:n,if (W(u,v)+dist(u)<dist(v)),
dist(v)=dist(u)+W(u,v);parent(v)=u;
end;end;end
if parent(t)~=0,path=t;d=dist(t);%回溯最短路徑
while t~=s,p=parent(t);path=[p path];t=p;end;
end;
希望對你有用
尋路演算法實現
用Dijkstra演算法,我做的給你個參考,下面各點是有距離的(移動力),BIG表示不可通過
#define BIG 32767 //無窮大
int pre[6]={0}; //這是關鍵!pre數組用於記錄每個點的前趨,這樣算出最短路徑後,就可以遞迴出路徑經過的點
int Distance[6]; //用於記錄從起點到達每個點的最短路徑長度
int Cost[6][6]={{0,1450,1650,BIG,BIG,BIG}, //有向網的鄰接矩陣,這裡以6個點為例
????????{1450,0,BIG,1350,2350,BIG},
????????{1650,BIG,0,BIG,2550,BIG},
????????{BIG,1350,BIG,0,BIG,1200},
????????{BIG,2350,2550,BIG,0,850},
????????{BIG,BIG,BIG,1200,850,0},
????????};
//Dijkstra演算法函數,求給定點到其餘各點的最短路徑
//參數:鄰接矩陣、頂點數、出發點的下標、結果數組、每個點的前趨
void Dijkstra(int Cost[][6],int n,int v0,int Distance[],int pre[])
{
??int s[6];
??int mindis,dis;
??int i,j,u;
??//初始化
??for(i=0;i<n;i++) {
????Distance[i]=Cost[v0][i];
????s[i]=0;
??}
??s[v0] =1; //標記v0
??//在當前還未找到最短路徑的頂點中,尋找具有最短距離的頂點
??for(i=0;i<n;i++){
????if(Distance[i]<BIG) pre[i]=v0;
??}
??for(i=1;i<n;i++) { //每迴圈一次,求得一個最短路徑
????mindis=BIG;
????for (j=0;j<n;j++) //求離出發點最近的頂點
??????if(s[j]==0&&Distance[j]<mindis) {
????????mindis=Distance [j];
????????u=j;
??????}
????for(j=0;j<n;j++) //修改遞增路徑序列(集合)
??????if(s[j]==0) { //對還未求得最短路徑的頂點
????????//求出由最近的頂點 直達各頂點的距離
????????dis=Distance[u] +Cost[u][j];
????????//如果新的路徑更短,就替換掉原路徑
????????if(Distance[j]>dis){
??????????Distance[j]=dis;
??????????pre[j]=u;
????????}
??????}
????s[u]=1; // 標記最短路徑已經求得
??}
}
用Dijkstra函數算出最短路徑後,就可以遞迴出從給定頂點到各點的最短路徑上的每個點了,函數如下(......餘下全文>>