搜尋部落格文章

2012年6月19日 星期二

資料結構排序演算法


一、概論
對於數據的處理工作,排序是其最基本的運算之一。在當今的計算機系統中,花費在排序上的時間佔系統CPU運行時間的很大比重。有資料表明,在一些商用計算機上,在排序上的CPU時間達到20%至60%。為了提高計算機的工作效率,人們提出了各種各樣的排序方法和算法。這些算法有力地發展、並充分地展示了算法設計的某些重要原則和高超技巧。因此,對於計算專業人員來說掌握排序算法是十分重要的。

二、排序算法簡介
本次課程中我們將介紹六種排序方法:插入排序,選擇排序,冒泡排序,希爾排序,快速排序及二路歸併。

<1>直接選擇排序(Selection Sort):簡單的選擇排序,它的比較次數一定:n(n-1)/2。也因此無論在序列何種情況下,它都不會有優秀的表現(從上100K的正序和反序數據可以發現它耗時相差不多,相差的只是數據移動時間),可見對數據的有序性不敏感。它雖然比較次數多,但它的數據交換量卻很少。所以我們將發現它在一般情況下將快於冒泡排序。

<2>直接插入排序(Insertion Sort):簡單的插入排序,每次比較後最多移掉一個逆序,因此與冒泡排序的效率相同。但它在速度上還是要高點,這是因為在冒泡排序下是進行值交換,而在插入排序下是值移動,所以直接插入排序將要優於冒泡排序。直接插入法也是一種對數據的有序性非常敏感的一種算法。在有序情況下只需要經過n-1次比較,在最壞情況下,將需要n(n-1)/2次比較。

<3>冒泡排序(Bubble Sort):將相鄰的兩個數據元素按關鍵字進行比較,如果反序,則交換。對於一個待排序的數據元素序列,經一趟排序後最大值數據元素移到最大位置,其它值較大的數據元素向也最終位置移動,此過程為一次起泡。然後對下面的記錄重複上述過程直到過程中沒有交換為止,則已完成對記錄的排序。

<4>快速排序(Quick Sort):是冒泡排序的改進,它通過一次交換能消除多個逆序,這樣可以減少逆序時所消耗的掃描和數據交換次數。在最優情況下,它的排序時間複雜度為O(nlog2n)。即每次劃分序列時,能均勻分成兩個子串。但最差情況下它的時間複雜度將是O(n^2)。即每次劃分子串時,一串為空,另一串為m-1(程序中的100K正序和逆序就正是這樣,如果程序中採用每次取序列中部數據作為劃分點,那將在正序和逆時達到最優)。從100K中正序的結果上看“快速排序”會比“冒泡排序”更慢,這主要是“冒泡排序”中採用了提前結束排序的方法。有的書上這解釋“快速排序”,在理論上講,如果每次能均勻劃分序列,它將是最快的排序算法,因此稱它作快速排序。雖然很難均勻劃分序列,但就平均性能而言,它仍是基於關鍵字比較的內部排序算法中速度最快者。

<5>希爾排序(Shell Sort):增量的選擇將影響希爾排序的效率。但是無論怎樣選擇增量,最後一定要使增量為1,進行一次直接插入排序。但它相對於直接插入排序,由於在子表中每進行一次比較,就可能移去整個經性表中的多個逆序,從而改善了整個排序性能。希爾排序算是一種基於插入排序的算法,所以對數據有序敏感。

<6>歸併排序(Merge Sort):歸併排序是一種非就地排序,將需要與待排序序列一樣多的輔助空間。在使用它對兩個己有序的序列歸併,將有無比的優勢。其時間複雜度無論是在最好情況下還是在最壞情況下均是O(nlog2n)。對數據的有序性不敏感。若數據節點數據量大,那將不適合。但可改造成索引操作,效果將非常出色。

三、排序方法的選擇
因為不同的排序方法適應不同的應用環境和要求,所以選擇合適的排序方法很重要
(1)若n較小,可採用直接插入或直接選擇排序。
當記錄規模較小時,直接插入排序較好,它會比選擇更少的比較次數;
但當記錄規模較大時,因為直接選擇移動的記錄數少於直接插人,所以宜用選直接選擇排序。
這兩種都是穩定排序算法。

(2)若文件初始狀態基本有序(指正序),則應選用直接插人、冒泡或隨機的快速排序為宜(這裡的隨機是指基準取值的隨機,原因見上的快速排序分析);這裡快速排序算法將不穩定。

(3)若n較大,則應採用時間複雜度為O(nlog2n)的排序方法:快速排序、堆排序或歸併排序序。
快速排序是目前基於比較的內部排序中被認為是最好的方法,當待排序的關鍵字是隨機分佈時,快速排序的平均時間最短;
堆排序雖不會出現快速排序可能出現的最壞情況。但它需要建堆的過程。這兩種排序都是不穩定的。
歸併排序是穩定的排序算法,但它有一定數量的數據移動​​,所以我們可能過與插入排序組合,先獲得一定長度的序列,然後再合併,在效率上將有所提高。

(4)特殊的箱排序、基數排序
它們都是一種穩定的排序算法,但有一定的局限性:
1>關鍵字可分解。
2>記錄的關鍵字位數較少,如果密集更好
3>如果是數字時,最好是無符號的,否則將增加相應的映射複雜度,可先將其正負分開排序。


四、AS中排列數組
1.申請一個長度為n的數組A:
var n:Number = 400;
var A:Array = new Array(n);
for (i=0; i < n; i++) {
 A[i] = i;
}
trace(A);

2.將長度為n的數組打亂次序:
for (i=0; i < n; i++) {
 var ran = int(Math.random()*n);
 var temp = A[i];
 A[i] = A[ran];
 A[ran] = temp;
}
trace(A)

3.將數組中的所有元素倒排序:
A.reverse();
trace(A)


 五、AS實現排序算法:
在執行各各排序算法之前,已經默認存在一個亂序的數組A[400],默認代碼:

var n:Number = 400;
var A:Array = new Array(n);
for (i=0; i < n; i++) {
 A[i] = i;
}
for (i=0; i < n; i++) {
 var ran = int(Math.random()*n);
 var temp = A[i];
 A[i] = A[ran];
 A[ran] = temp;
}
 

1.直接插入排序

for (i = 0; i < n; i++) {
 var temp = A[i];
 for (j = i; j > 0 && temp < A[j - 1]; j--) {
  A[j] = A[j - 1];
  A[j - 1] = temp;
 }
}


2.直接選擇排序

for (i = 0; i < n - 1; i++) {
 var s:Number = i;
 for (j = s + 1; j < n; j++) {
  if (A[j] < A[s]) {
   s = j;
  }
 }
 var temp = A[i];
 A[i] = A[s];
 A[s] = temp;
}


3.冒泡排序

for (i = 0; i < n; i++) {
 for (j = i; j < n; j++) {
  if (A[i] > A[j]) {
   var temp = A[i];
   A[i] = A[j];
   A[j] = temp;
  }
 }
}


4.希爾排序

var increment = 6;
while (increment > 1) {
 increment = int(increment / 3 + 1);
 Shellpass(increment);
}
function Shellpass(c) {
 for (i = c; i < n; i++) {
  if (A[i] < A[i - c]) {
   var temp = A[i];
   j = i - c;
   do {
    A[j + c] = A[j];
    j = j - c;
   } while (j > 0 && temp < A[j]);
   A[j + c] = temp;
  }
 }
}


5.快速排序

function QuickSort(A, low, hig) {
 var i = low, j = hig;
 var mid = A[int((low + hig) / 2)];
 do {
  while (A[i] < mid) {
   i++;
  }
  while (A[j] > mid) {
   j--;
  }
  if (i <= j) {
   var temp = A[i];
   A[i] = A[j];
   A[j] = temp;
   i++;
   j--;
  }
 } while (i <= j);
 if (low < j) {
  arguments.callee(A,low,j);
 }
 if (i < hig) {
  arguments.callee(A,i,hig);
 }
}
QuickSort(A,0,n - 1);


6.二路歸併

var B:Array = new Array(A.length);
for (k = 1; k < n; k *= 2) {
 MergePass(k);
}
function MergePass(len) {
 for (i = 0; i + 2 * len < n; i = i + 2 * len) {
  MergeA(i,i + len - 1,i + 2 * len - 1);
 }
 if (i + len < n) {
  MergeA(i,i + len - 1,n - 1);
 }
}
function MergeA(low, m, hig) {
 var i = low, j = m + 1, z = 0;
 while (i <= m && j <= hig) {
  B[z++] = (A[i] <= A[j]) ? A[i++] : A[j++];
 }
 while (i <= m) {
  B[z++] = A[i++];
 }
 while (j <= hig) {
  B[z++] = A[j++];
 }
 for (z = 0, i = low; i <= hig; z++, i++) {
  A[i] = B[z];
 }
}

2012年6月15日 星期五

Object資料的深複製


AS3中很常使用(flash.utils.ByteArray)類別來進行物件的深複製,

複製並非參照,而是複製整個物件。
可以寫一個方法來進行Object的深複製(

注意:這個方法通常用來拷貝一般Object)

function clone(source:Object):* {
 var copier:ByteArray = new ByteArray();
 copier.writeObject(source);
 copier.position = 0;
 return(copier.readObject());
}


使用方法: 
var newObject = clone(originalObject);

ActionScript 命名規則定義

基本上變數常數都是私有的(private),如需被外部採用,則透過public function get方式開放

變數

  • private var _variable
  • public var variable public  function get variable
  • private static var _variable
  • public static var _variable  public function get variable
常數
  • private const _VARIABLE
  • public const VARIABLE  public function get VARIABLE
  • private static  _VARIABLE
  • public const VARIABLE  public static function get VARIABLE
取用方式
  • 全域變數 this._variable (特徵:this+變數名稱)
  • 全域靜態 Class._variable  (特徵:類別名稱+變數名)
  • 區域變數 variable (特徵:無底線,沒有參照this)

2012年6月11日 星期一

Adobe Flash CS6 CS5.5 本機Help文件

Flash本機Help文件

官方線上的真的很難用,搜尋老是跑出一些不是我要的東西,一直去找線上論壇的資料

記得先執行 Adobe Help應用程式,更新所有的Help文件,才可以找到下列路徑。



Windows 7


CS5.5&CS5
C:\Users\Jay\AppData\Roaming\chc.4875E02D9FB21EE389F73B8D1702B320485DF8CE.1\Local Store\Help\zh_TW\FlashPlatform\reference\actionscript\3

CS6
C:\Users\Public\Documents\Adobe\Help\zh_TW\FlashPlatform\reference\actionscript\3