快速排序_qsort排序结构-程序员宅基地

技术标签: 算法  random  concatenation  numbers  PHP  pivot  object  

 快速排序(Quicksort)是一種眾所周知的排序算法,由C. A. R. Hoare所發展的,以平均效能來說,排序 n 個項目要Θ(n log n)次比較。然而,在最壞的效能下,它需要Θ(n2)次比較。一般來說,快速排序實際上明顯地比其他Θ(n log n) 演算法更快,因為它的內部回圈(inner loop)可以在大部分的架構上很有效率地被實作出來,且在大部分真實世界的資料,可以決定設計的選擇,減少所需時間的二次方項之可能性。

 

演算法

快速排序是一種「分而治之、各個擊破」的觀念。

快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。

步驟為:

  1. 從數列中挑出一個元素,稱為 "基準"(pivot),
  2. 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割之後,該基準是它的最後位置。這個稱為分割(partition)操作。
  3. 递归地(recursive)把小於基准值元素的子數列和大於基准值元素的子數列排序。

遞迴的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞迴下去,但是這個演算法總會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。

在簡單的虛擬碼中,演算法可以被表示為:

 function quicksort(q)
     var list less, pivotList, greater
     if length(q) ≤ 1 {
         return q
     } else {
         select a pivot value pivot from q
         for each x in q except the pivot element
             if x < pivot then add x to less
             if x ≥ pivot then add x to greater
         add pivot to pivotList
         return concatenate(quicksort(less), pivotList, quicksort(greater))
     }

[编辑] 原地(in-place)分割的版本

上面簡單版本的缺點是,它需要Ω(n)的額外儲存空間,也就跟归并排序一樣不好。額外需要的記憶體空間配置,在實際上的實作,也會極度影響速度和快取的效能。有一個比較複雜使用原地(in-place)分割算法的版本,且在好的基準選擇上,平均可以達到O(log n)空間的使用複雜度。

 function partition(a, left, right, pivotIndex)
     pivotValue := a[pivotIndex]
     swap(a[pivotIndex], a[right]) // 把 pivot 移到結尾
     storeIndex := left
     for i from left to right-1
         if a[i] <= pivotValue
             swap(a[storeIndex], a[i])
             storeIndex := storeIndex + 1
     swap(a[right], a[storeIndex]) // 把 pivot 移到它最後的地方
     return storeIndex

這是原地分割演算法,它分割了標示為 "左邊(left)" 和 "右邊(right)" 的序列部份,藉由移動小於a[pivotIndex]的所有元素到子序列的開頭,留下所有大於或等於的元素接在他們後面。在這個過程它也為基準元素找尋最後擺放的位置,也就是它回傳的值。它暫時地把基準元素移到子序列的結尾,而不會被前述方式影響到。由於演算法只使用交換,因此最後的數列與原先的數列擁有一樣的元素。要注意的是,一個元素在到達它的最後位置前,可能會被交換很多次。

一旦我們有了這個分割演算法,要寫快速排列本身就很容易:

 function quicksort(a, left, right)
     if right > left
         select a pivot value a[pivotIndex]
         pivotNewIndex := partition(a, left, right, pivotIndex)
         quicksort(a, left, pivotNewIndex-1)
         quicksort(a, pivotNewIndex+1, right)

這個版本經常會被使用在命令式語言中,像是C語言

[编辑] 競爭的排序演算法

快速排序是二叉查找树(二元搜尋樹)的一個空間最佳化版本。不以循序地把項目插入到一個明確的樹中,而是由快速排序組織這些項目到一個由遞迴呼叫所意含的樹中。這兩個演算法完全地產生相同的比較次數,但是順序不同。

快速排序的最直接競爭者是堆排序(Heapsort)。堆排序通常比快速排序稍微慢,但是最壞情況的執行時間總是O(n log n)。快速排序是經常比較快,除了introsort變化版本外,仍然有最壞情況效能的機會。如果事先知道堆排序將會是需要使用的,那麼直接地使用堆排序比等待 introsort 再切換到它還要快。堆排序也擁有重要的特點,僅使用固定額外的空間(堆排序是原地排序),而即使是最佳的快速排序變化版本也需要Θ(log n)的空間。然而,堆排序需要有效率的隨機存取才能變成可行。

快速排序也與归并排序(Mergesort)競爭,這是另外一種遞迴排序算法,但有壞情況O(n log n)執行時間的優勢。不像快速排序或堆排序,归并排序是一個穩定排序,且可以輕易地被採用在鏈串列(linked list)和儲存在慢速存取媒體上像是磁碟儲存網路連接儲存的非常巨大數列。儘管快速排序可以被重新改寫使用在鍊串列上,但是它通常會因為無法隨機存取而導致差的基準選擇。归并排序的主要缺點,是在最佳情況下需要Ω(n)額外的空間。

[编辑] 正規的分析

從一開始快速排序平均需要花費O(n log n)時間的描述並不明顯。但是不難觀察到的是分割運算,陣列的元素都會在每次迴圈中走訪過一次,使用Θ(n)的時間。在使用結合(concatenation)的版本中,這項運算也是Θ(n)。

在最好的情況,每次我們執行一次分割,我們會把一個數列分為兩個幾近相等的片段。這個意思就是每次遞迴呼叫處理一半大小的數列。因此,在到達大小為一的數列前,我們只要作 log n 次巢狀的呼叫。這個意思就是呼叫樹的深度是O(log n)。但是在同一階層的兩個程序呼叫中,不會處理到原來數列的相同部份;因此,程序呼叫的每一階層總共全部僅需要O(n)的時間(每個呼叫有某些共同的額外耗費,但是因為在每一階層僅僅只有O(n)個呼叫,這些被歸納在O(n)係數中)。結果是這個演算法僅需使用O(n log n)時間。

另外一個方法是為T(n)設立一個遞迴關係式,也就是需要排序大小為n的數列所需要的時間。在最好的情況下,因為一個單獨的快速排序呼叫牽涉了O(n)的工作,加上對n/2大小之數列的兩個遞迴呼叫,這個關係式可以是:

T( n) = O( n) + 2T( n/2)

解決這種關係式型態的標準数学归纳法技巧告訴我們T(n) = Θ(n log n)。

事實上,並不需要把數列如此精確地分割;即使如果每個基準值將元素分開為 99% 在一邊和 1% 在另一邊,呼叫的深度仍然限制在 100log n,所以全部執行時間依然是O(n log n)。

然而,在最壞的情況是,兩子數列擁有大各為 1 和 n-1,且呼叫樹(call tree)變成為一個 n 個巢狀(nested)呼叫的線性連串(chain)。第 i 次呼叫作了O(n-i)的工作量,且/sum_{i=0}^n (n-i) = O(n^2)遞迴關係式為:

T( n) = O( n) + T(1) + T( n - 1) = O( n) + T( n - 1)

這與插入排序选择排序有相同的關係式,以及它被解為T(n) = Θ(n2)。

[编辑] 亂數快速排序的期望複雜度

不管輸入怎樣下,亂數快速排序擁有得當的特性,也就是它只需要O(n log n)期望的時間。是什麼讓隨機的基準變成一個好的選擇?

假設我們排序一個數列,然後把它分為四個部份。在中央的兩個部份將會包含最好的基準值;他們的每一個至少都會比25%的元素大,且至少比25%的元素小。如果我們可以一致地從這兩個中央的部份選出一個元素,在到達大小為1的數列前,我們可能最多僅需要把數列分割2log2 n次,產生一個 O(nlogn)演算法。

不幸地,亂數選擇只有一半的時間會從中間的部份選擇。出人意外的事實是這樣就已經足夠好了。想像你正在翻轉一枚硬幣,一直翻轉一直到有 k 次人頭那面出現。儘管這需要很長的時間,平均來說只需要 2k 次翻動。且在 100k 次翻動中得到 k 次人頭那面的機會,是像天文數字一樣的非常小。藉由同樣的論證,快速排序的遞迴平均只要2(2log2 n)的呼叫深度就會終止。但是如果它的平均呼叫深度是O(log n)且每一階的呼叫樹狀過程最多有 n 個元素,則全部完成的工作量平均上是乘積,也就是 O(n log n)。

[编辑] 平均複雜度

即使如果我們無法隨機地選擇基準數值,對於它的輸入之所有可能排列,快速排序仍然只需要O(n log n)時間。因為這個平均是簡單地將輸入之所有可能排列的時間加總起來,除以n這個因數,相當於從輸入之中選擇一個隨機的排列。當我們這樣作,基準值本質上就是隨機的,導致這個演算法與亂數快速排序有一樣的執行時間。

更精確地說,對於輸入順序之所有排列情形的平均比較次數,可以藉由解出這個遞迴關係式可以精確地算出來。

C(n) = n - 1 + /frac{1}{n} /sum_{i=0}^{n-1} (C(i)+C(n-i-1)) = 2n /ln n = 1.39n /log_2 n.

在這裡,n-1 是分割所使用的比較次數。因為基準值是相當均勻地落在排列好的數列次序之任何地方,總和就是所有可能分割的平均。

這個意思是,平均上快速排序比理想的比較次數,也就是最好情況下,只大約比較糟39%。這意味著,它比最壞情況較接近最好情況。這個快速的平均執行時間,是快速排序比其他排序演算法有實際的優勢之另一個原因。

[编辑] 空間複雜度

被快速排序所使用的空間,依照使用的版本而定。使用原地(in-place)分割的快速排序版本,在任何遞迴呼叫前,僅會使用固定的額外空間。然而,如果需要產生O(log n)巢狀遞迴呼叫,它需要在他們每一個儲存一個固定數量的資訊。因為最好的情況最多需要O(log n)次的巢狀遞迴呼叫,所以它需要O(log n)的空間。最壞情況下需要O(n)次巢狀遞迴呼叫,因此需要O(n)的空間。

然而我們在這裡省略一些小的細節。如果我們考慮排序任意很長的數列,我們必須要記住我們的變數像是leftright,不再被認為是佔據固定的空間;也需要O(log n)對原來一個n項的數列作索引。因為我們在每一個堆疊框架中都有像這些的變數,實際上快速排序在最好跟平均的情況下,需要O(log2 n)空間的位元數,以及最壞情況下O(n log n)的空間。然而,這並不會太可怕,因為如果一個數列大部份都是不同的元素,那麼數列本身也會佔據O(n log n)的空間位元組。

非原地版本的快速排序,在它的任何遞迴呼叫前需要使用O(n)空間。在最好的情況下,它的空間仍然限制在O(n),因為遞迴的每一階中,使用與上一次所使用最多空間的一半,且

/sum_{i=0}^{/infty} /frac{n}{2^i} = 2n.

它的最壞情況是很恐怖的,需要

/sum_{i=0}^n (n-i+1) = /Theta (n^2)

空間,遠比數列本身還多。如果這些數列元素本身自己不是固定的大小,這個問題會變得更大;舉例來說,如果數列元素的大部份都是不同的,每一個將會需要大約O(log n)為原來儲存,導致最好情況是O(n log n)和最壞情況是O(n2 log n)的空間需求。

[编辑] 選擇的關連性

選擇算法(selection algorithm)可以選取一個數列的第k個最小值;一般而言這是比排序還簡單的問題。一個簡單但是有效率的選擇算法與快速排序的作法相當類似,除了對兩個子數列都作遞迴呼叫外,它僅僅針對包含想要的元素之子數列作單一的結尾遞迴(tail recursive)呼叫。這個小改變降低了平均複雜度到線性或是Θ(n)時間,且讓它成為一個原地算法。這個算法的一種變化版本,可已讓最壞情況下降為O(n)(參考選擇算法來得到更多資訊)。

相反地,一旦我們知道一個最壞情況的O(n)選擇算法是可以利用的,我們在快速排序的每一步可以用它來找到理想的基準(中位數),得到一種最化情況下O(n log n)執行時間的變化版本。在實際的實作,然而這種版本一般而言相當的慢。

[编辑] 實作範例

主条目: 快速排序實作

於此我們展示在數種語言下的幾個快速排序實作。我們在此僅秀出最普遍或獨特的一些;針對其他的實作,參見快速排序實作條目。

[编辑] C

排序一個整數的陣列

void swap(int *a, int *b)
{ 
  int t=*a; *a=*b; *b=t; 
}
void sort(int arr[], int beg, int end) 
{
  if (end > beg + 1) 
  {
  int piv = arr[beg], k = beg + 1, r = end;
    
    while (k < r) 
    {
      if (arr[k] <= piv) 
        k++;
      else 
        swap(&arr[k], &arr[--r]);
    }
    swap(&arr[--k], &arr[beg]);
    sort(arr, beg, k);
    sort(arr, r, end);
  }
}

[编辑] C++

這是一個使用标准模版库(STL)的泛型式快速排序版本。

#include <functional>
#include <algorithm>
#include <iterator>

template< typename BidirectionalIterator, typename Compare >
void quick_sort( BidirectionalIterator first, BidirectionalIterator last, Compare cmp ) {
  if( first != last ) {
    BidirectionalIterator left  = first;
    BidirectionalIterator right = last;
    BidirectionalIterator pivot = left++;

    while( left != right ) {
      if( cmp( *left, *pivot ) ) {
         ++left;
      } else {
         while( (left != right) && cmp( *pivot, *right ) )
           right--;
         std::iter_swap( left, right );
      }
    }

    if cmp( *pivot, *left )
         --left;
    std::iter_swap( first, left );

    quick_sort( first, left, cmp );
    quick_sort( right, last, cmp );
  }
}

template< typename BidirectionalIterator >
inline void quick_sort( BidirectionalIterator first, BidirectionalIterator last ) {
  quick_sort( first, last,
    std::less_equal< typename std::iterator_traits< BidirectionalIterator >::value_type >()
  );
}

[编辑] Java

import java.util.Comparator;
import java.util.Random;

public class Quicksort {
    public static final Random RND = new Random();

    private void swap(Object[] array, int i, int j) {
        Object tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

    private int partition(Object[] array, int begin, int end, Comparator cmp) {
        int index = begin + RND.nextInt(end - begin + 1);
        Object pivot = array[index];
        swap(array, index, end);	
        for (int i = index = begin; i < end; ++ i) {
            if (cmp.compare(array[i], pivot) <= 0) {
                swap(array, index++, i);
            }
        }
        swap(array, index, end);	
        return (index);
    }

    private void qsort(Object[] array, int begin, int end, Comparator cmp) {
        if (end > begin) {
            int index = partition(array, begin, end, cmp);
            qsort(array, begin, index - 1, cmp);
            qsort(array, index + 1,  end,  cmp);
        }
    }

    public void sort(Object[] array, Comparator cmp) {
        qsort(array, 0, array.length - 1, cmp);
    }
}

[编辑] Python

def qsort(L):
   if L == []: return []
   return qsort([x for x in L[1:] if x< L[0]]) + L[0:1] + /
          qsort([x for x in L[1:] if x>=L[0]])

[编辑] Joy

DEFINE sort == [small][]
               [uncons [>] split]
               [[swap] dip cons concat] binrec .

[编辑] PHP

function quicksort($seq) {
  if (count($seq) > 1) {
    $k = $seq[0];
    $x = array();
    $y = array();
    for ($i=1; $i<count($seq); $i++) {
      if ($seq[$i] <= $k) {
        $x[] = $seq[$i];
      } else {
        $y[] = $seq[$i];
      }
    }
    $x = quicksort($x);
    $y = quicksort($y);
    return array_merge($x, array($k), $y);
  } else {
    return $seq;
  }
}

[编辑] Haskell

 sort :: (Ord a)   => [a] -> [a]
 
 sort []           = []
 sort (pivot:rest) = sort [y | y <- rest, y < pivot]
                     ++ [pivot] ++ 
                     sort [y | y <- rest, y >=pivot]

[编辑] Prolog

split(H, [A|X], [A|Y], Z) :-
  order(A, H), split(H, X, Y, Z).
split(H, [A|X], Y, [A|Z]) :-
  not(order(A, H)), split(H, X, Y, Z).
split(_, [], [], []).

quicksort([], X, X).

quicksort([H|T], S, X) :-
  split(H, T, A, B),
  quicksort(A, S, [H|Y]),
  quicksort(B, Y, X).

[编辑] Ruby

def sort(array)
  # return [] if array.empty?
  return array if array.size < 2
  left, right = array[1..-1].partition { |y| y <= array.first }
  sort(left) + [ array.first ] + sort(right)
end

[编辑] SML

This example demonstrates the use of an arbitrary predicate in a functional language.

fun quicksort lt lst =
  let val rec sort =
    fn [] => []
     | (x::xs) =>
        let
          val (left,right) = List.partition (fn y => lt (y, x)) xs
        in sort left @ x :: sort right
        end
  in sort lst
end

[编辑] Pascal

program QSort;
const
  Max = 1000;

var
  Data: List;
  I: Integer;

procedure Sort(l, r: Integer);

var
  i, j, x, y: integer;
begin
  i := l; j := r; x := Data[(l+r) DIV 2];
  repeat
    while Data[i] < x do i := i + 1;
    while x < Data[j] do j := j - 1;
    if i <= j then
    begin
      y := Data[i]; Data[i] := Data[j]; Data[j] := y;
      i := i + 1; j := j - 1;
    end;
  until i > j;
  if l < j then Sort(l, j);
  if i < r then Sort(i, r);
end;

begin {QSort}
  Randomize;
  for i := 1 to Max do Data[i] := Random(30000);
  Sort(1, Max);
  Writeln;
  for i := 1 to 1000 do Write(Data[i]:8);
end.

[编辑] C#

       public static void Sort(int[] numbers)
        {
     
            Sort(numbers, 0, numbers.Length - 1);
        }
 
        private static void Sort(int[] numbers, int left, int right)
        {
     
            if (left < right)
            {
     
                int middle = numbers[(left + right) / 2];
                int i = left - 1;
                int j = right + 1;
                while (true)
                {
     
                    while (numbers[++i] < middle) ;
 
                    while (numbers[--j] > middle) ;
 
                    if (i >= j)
                        break;
 
                    Swap(numbers, i, j);
                }
 
                Sort(numbers, left, i - 1);
                Sort(numbers, j + 1, right);
            }
        }
 
        private static void Swap(int[] numbers, int i, int j)
        {
     
            int number = numbers[i];
            numbers[i] = numbers[j];
            numbers[j] = number;
        }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wssxy/article/details/3448642

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文