A. java 分治法 求解一組數組元素的最大值和最小值
//求一個數組A[i...j]的最大值和最小值,分支演算法,遞歸實現//2015.2.9//devc++#include<stdio.h>#include<malloc.h>intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}int*MaxMin(inta[],inti,intj){int*m=(int*)malloc(2*sizeof(int));if(j-i+1==1){m[0]=m[1]=a[i];returnm;}if(j-i+1==2){if(a[i]<a[j]){m[0]=a[i];m[1]=a[j];}else{m[0]=a[j];m[1]=a[i];}returnm;}intk=(j-i+1)/2;int*m1=MaxMin(a,i,k);int*m2=MaxMin(a,k+1,j);m[0]=min(m1[0],m2[0]);m[1]=max(m1[1],m2[1]);returnm;}intmain(){inta[128];intn;inti;while(scanf("%d",&n)!=EOF){for(i=0;i<n;i++){scanf("%d",&a[i]);}int*m=MaxMin(a,0,n-1);printf("%d%d ",m[0],m[1]);}return0;}B. 分治法求x的n次方的JAVA程序
計算X的n次方
public static int power(int x, int n)
{
int y = 0;
if (n == 0)
y = 1;
else
{
y = power(x , n/2); //遞歸
y = y * y;
if (y % 2 == 1)
y = y * x;
}
return y;
}
C. 求問 這個java方法的時間復雜度是怎麼樣的 請問怎麼計算
給出的代碼時間復雜度應該是o(n),時間復雜度就是關鍵代碼的執行次數的指數,比如for(){
for(){}
}
這種嵌套循環應該就是o(n²)
D. java中抽象的最主要的特徵是什麼
抽象的定義
抽象,就是指有意地壓縮或隱藏過程或產品細節,以便得到更清晰的表現、細節或結構。
抽象,是控制復雜性時最重要的工具。
抽象實例:地圖集
如果打開一本地圖集,一般看到的常是一幅世界地圖。該地圖只顯示了一些最主要的特徵,如主要的山脈、海洋等等,但細節基本上都被忽略了。
隨後的一系列地圖將覆蓋小一些的地理區域,也能處理更多的細節。例如,一塊大陸(如各大洲)的地圖將包括國家的邊界和主要的國家。更小的區域(如國家)地圖,將包括城市、各山峰的名稱。一個城市的地圖可能會包括進出該城市的主要道路,再小一些的地圖甚至還會畫出一些建築物。
每個抽象層次,包括了某些信息,也忽略了某些信息
我們注意到,在每一個層次上,有些信息被包括進來了,而另一些信息被忽略了。這只是因為在較高的層次上,無法表現所有的細節。即使能夠表現,也沒有人能夠處理這么大量的信息。因此,很多細節被忽略了。
人們通常使用一些簡單的工具來建立、理解和管理復雜的系統。其中最重要的技術稱為「抽象」(abstraction)。
信息隱藏
信息隱藏是指在建立抽象表示時有意地省略一些細節。
信息隱藏使得抽象可以控制復雜性。
抽象的層次
在典型的OOP程序中,有許多級抽象。其中,最高的級別是使該程序能夠面向對象的部分。
在最高級別上,程序被視為一個對象的「團體」,這些對象間相互作用,以完成共同的目標。
團體:兩層含義
在面向對象程序開發過程中,關於「團體」有兩個層次的含義:
首先是指程序員的團體,他們在現實世界中相互作用,以便開發出應用程序來。
第二個團體是這些程序員創建的對象的團體,它們在虛擬世界中相互作用,以完成它們的共同目標。
關鍵之處在於信息隱藏,以及每個層次都進行抽象
抽象的最高級,要突出團體和合作
團體中的每個對象都提供一種被組織中的其他成員使用的服務。
在抽象的最高級別,最重要的是要突出團體和合作,以及成員與其他成員交互的方式。
許多語言允許協同工作的對象組合到一個「單元」(unit)中。例如,Java的「包」 packages,C++的「名字空間」name spaces,Delphi中的「單元」(units)。這些單元向單元外的世界顯露一些特徵,而其他特徵則隱藏在單元中。
兩層抽象:服務者和客戶
兩個對象間交互時涉及兩層抽象:一個對象(服務者, server)向另一個對象(客戶, client)提供服務,二者之間以通信來交互。
術語的用法:server和client
這里的server不是指伺服器(如網站伺服器,web server),而是指提供服務的服務者。
該個抽象涉及一個關系的兩個視角:從客戶這一邊的視角,及從服務者這一方的視角。
在具有良好的面向對象風格的設計中,我們在描述和討論服務者提供的服務時,不必考慮客戶在使用這些服務時的情況
從服務者這一層次的抽象,要考慮如何實現抽象的行為
最終層次的抽象,就是一個方法,它實現了完成任務所需的操作序列。
確定合適層次的抽象
在軟體開發的早期,關鍵的問題就是確定合適層次的抽象。
既不要忽略太多的細節,也不要包括太多的細節。
抽象形式:分治法
常用的一種抽象形式是將一層劃分為多個組成部分。
例如,汽車是由發動機、傳動機構、車身和車輪組成的。
要理解汽車這個概念,只要依次檢查其組成部件就行了。這就是傳統的分治法(divide and conquer).
抽象形式:特殊化(具體化、專門化)
另一種抽象形式稱為特殊化或具體化(specialization).
如,汽車是一個有輪的載運工具,而有輪的載運工具又是一個載運工具。
我們所了解的關於有輪的載運工具的知識,同樣適用於汽車和自行車。
我們所了解的關於載運工具的知識,同樣適用於馬匹和自行車。
面向對象的語言,常常使用這種形式的抽象
抽象形式:不同視角
另一種形式的抽象,是對同一件物品提供不同的視角。每一個視角會強調某一些細節而忽略其他細節,因此,對同一對象描述出不同的特性。
例如,大眾眼裡的汽車和技工眼裡的汽車,看法是很不一樣的。
「是一個」與「有一個」抽象
分治法與特殊化,代表了面向對象語言中最常用的兩種抽象形式,一般稱為「是一個」(is-a)和「有一個」(has-a)抽象。
分治法:「有一個」抽象
分治法是「有一個」抽象。
例如,一輛汽車「有一個」發動機,「有一個」傳動機構,等等。
特殊化:「是一個」抽象
特殊化為「是一個」抽象。
例如,自行車「是一個」有輪載運工具,有輪載運工具「是一個」載運工具。
E. Java中二維數組排序的問題
文章
java數組排序2009年09月12日 星期六 下午 12:55import java.util.Random;
/**
* 排序測試類
*
* 排序演算法的分類如下:
* 1.插入排序(直接插入排序、折半插入排序、希爾排序);
* 2.交換排序(冒泡泡排序、快速排序);
* 3.選擇排序(直接選擇排序、堆排序);
* 4.歸並排序;
* 5.基數排序。
*
* 關於排序方法的選擇:
* (1)若n較小(如n≤50),可採用直接插入或直接選擇排序。
* 當記錄規模較小時,直接插入排序較好;否則因為直接選擇移動的記錄數少於直接插人,應選直接選擇排序為宜。
* (2)若文件初始狀態基本有序(指正序),則應選用直接插人、冒泡或隨機的快速排序為宜;
* (3)若n較大,則應採用時間復雜度為O(nlgn)的排序方法:快速排序、堆排序或歸並排序。
*
* @author WangRuifeng
*/
public class SortTest {
/**
* 初始化測試數組的方法
* @return 一個初始化好的數組
*/
public int[] createArray() {
Random random = new Random();
int[] array = new int[10];
for (int i = 0; i < 10; i++) {
array[i] = random.nextInt(100) - random.nextInt(100);//生成兩個隨機數相減,保證生成的數中有負數
}
System.out.println("==========原始序列==========");
printArray(array);
return array;
}
/**
* 列印數組中的元素到控制台
* @param source
*/
public void printArray(int[] source) {
for (int i : source) {
System.out.print(i + " ");
}
System.out.println();
}
/**
* 交換數組中指定的兩元素的位置
* @param source
* @param x
* @param y
*/
private void swap(int[] source, int x, int y) {
int temp = source[x];
source[x] = source[y];
source[y] = temp;
}
/**
* 冒泡排序----交換排序的一種
* 方法:相鄰兩元素進行比較,如有需要則進行交換,每完成一次循環就將最大元素排在最後(如從小到大排序),下一次循環是將其他的數進行類似操作。
* 性能:比較次數O(n^2),n^2/2;交換次數O(n^2),n^2/4
*
* @param source 要排序的數組
* @param sortType 排序類型
* @return
*/
public void bubbleSort(int[] source, String sortType) {
if (sortType.equals("asc")) { //正排序,從小排到大
for (int i = source.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (source[j] > source[j + 1]) {
swap(source, j, j + 1);
}
}
}
} else if (sortType.equals("desc")) { //倒排序,從大排到小
for (int i = source.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (source[j] < source[j + 1]) {
swap(source, j, j + 1);
}
}
}
} else {
System.out.println("您輸入的排序類型錯誤!");
}
printArray(source);//輸出冒泡排序後的數組值
}
/**
* 直接選擇排序法----選擇排序的一種
* 方法:每一趟從待排序的數據元素中選出最小(或最大)的一個元素, 順序放在已排好序的數列的最後,直到全部待排序的數據元素排完。
* 性能:比較次數O(n^2),n^2/2
* 交換次數O(n),n
* 交換次數比冒泡排序少多了,由於交換所需CPU時間比比較所需的CUP時間多,所以選擇排序比冒泡排序快。
* 但是N比較大時,比較所需的CPU時間佔主要地位,所以這時的性能和冒泡排序差不太多,但毫無疑問肯定要快些。
*
* @param source 要排序的數組
* @param sortType 排序類型
* @return
*/
public void selectSort(int[] source, String sortType) {
if (sortType.equals("asc")) { //正排序,從小排到大
for (int i = 0; i < source.length; i++) {
for (int j = i + 1; j < source.length; j++) {
if (source[i] > source[j]) {
swap(source, i, j);
}
}
}
} else if (sortType.equals("desc")) { //倒排序,從大排到小
for (int i = 0; i < source.length; i++) {
for (int j = i + 1; j < source.length; j++) {
if (source[i] < source[j]) {
swap(source, i, j);
}
}
}
} else {
System.out.println("您輸入的排序類型錯誤!");
}
printArray(source);//輸出直接選擇排序後的數組值
}
/**
* 插入排序
* 方法:將一個記錄插入到已排好序的有序表(有可能是空表)中,從而得到一個新的記錄數增1的有序表。
* 性能:比較次數O(n^2),n^2/4
* 復制次數O(n),n^2/4
* 比較次數是前兩者的一般,而復制所需的CPU時間較交換少,所以性能上比冒泡排序提高一倍多,而比選擇排序也要快。
*
* @param source 要排序的數組
* @param sortType 排序類型
*/
public void insertSort(int[] source, String sortType) {
if (sortType.equals("asc")) { //正排序,從小排到大
for (int i = 1; i < source.length; i++) {
for (int j = i; (j > 0) && (source[j] < source[j - 1]); j--) {
swap(source, j, j - 1);
}
}
} else if (sortType.equals("desc")) { //倒排序,從大排到小
for (int i = 1; i < source.length; i++) {
for (int j = i; (j > 0) && (source[j] > source[j - 1]); j--) {
swap(source, j, j - 1);
}
}
} else {
System.out.println("您輸入的排序類型錯誤!");
}
printArray(source);//輸出插入排序後的數組值
}
/**
* 反轉數組的方法
* @param source 源數組
*/
public void reverse(int[] source) {
int length = source.length;
int temp = 0;//臨時變數
for (int i = 0; i < length / 2; i++) {
temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
printArray(source);//輸出到轉後數組的值
}
/**
* 快速排序
* 快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。
* 步驟為:
* 1. 從數列中挑出一個元素,稱為 "基準"(pivot),
* 2. 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割之後,該基準是它的最後位置。這個稱為分割(partition)操作。
* 3. 遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。
* 遞回的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞回下去,但是這個演算法總會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。
* @param source 待排序的數組
* @param low
* @param high
* @see SortTest#qsort(int[], int, int)
* @see SortTest#qsort_desc(int[], int, int)
*/
public void quickSort(int[] source, String sortType) {
if (sortType.equals("asc")) { //正排序,從小排到大
qsort_asc(source, 0, source.length - 1);
} else if (sortType.equals("desc")) { //倒排序,從大排到小
qsort_desc(source, 0, source.length - 1);
} else {
System.out.println("您輸入的排序類型錯誤!");
}
}
/**
* 快速排序的具體實現,排正序
* @param source
* @param low
* @param high
*/
private void qsort_asc(int source[], int low, int high) {
int i, j, x;
if (low < high) { //這個條件用來結束遞歸
i = low;
j = high;
x = source[i];
while (i < j) {
while (i < j && source[j] > x) {
j--; //從右向左找第一個小於x的數
}
if (i < j) {
source[i] = source[j];
i++;
}
while (i < j && source[i] < x) {
i++; //從左向右找第一個大於x的數
}
if (i < j) {
source[j] = source[i];
j--;
}
}
source[i] = x;
qsort_asc(source, low, i - 1);
qsort_asc(source, i + 1, high);
}
}
/**
* 快速排序的具體實現,排倒序
* @param source
* @param low
* @param high
*/
private void qsort_desc(int source[], int low, int high) {
int i, j, x;
if (low < high) { //這個條件用來結束遞歸
i = low;
j = high;
x = source[i];
while (i < j) {
while (i < j && source[j] < x) {
j--; //從右向左找第一個小於x的數
}
if (i < j) {
source[i] = source[j];
i++;
}
while (i < j && source[i] > x) {
i++; //從左向右找第一個大於x的數
}
if (i < j) {
source[j] = source[i];
j--;
}
}
source[i] = x;
qsort_desc(source, low, i - 1);
qsort_desc(source, i + 1, high);
}
}
/**
* 二分法查找
* 查找線性表必須是有序列表
*
* @param source
* @param key
* @return
*/
public int binarySearch(int[] source, int key) {
int low = 0, high = source.length - 1, mid;
while (low <= high) {
mid = (low + high) >>> 1; //相當於mid = (low + high) / 2,但是效率會高些
if (key == source[mid]) {
return mid;
} else if (key < source[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
public static void main(String[] args) {
SortTest sortTest = new SortTest();
int[] array = sortTest.createArray();
System.out.println("==========冒泡排序後(正序)==========");
sortTest.bubbleSort(array, "asc");
System.out.println("==========冒泡排序後(倒序)==========");
sortTest.bubbleSort(array, "desc");
array = sortTest.createArray();
System.out.println("==========倒轉數組後==========");
sortTest.reverse(array);
array = sortTest.createArray();
System.out.println("==========選擇排序後(正序)==========");
sortTest.selectSort(array, "asc");
System.out.println("==========選擇排序後(倒序)==========");
sortTest.selectSort(array, "desc");
array = sortTest.createArray();
System.out.println("==========插入排序後(正序)==========");
sortTest.insertSort(array, "asc");
System.out.println("==========插入排序後(倒序)==========");
sortTest.insertSort(array, "desc");
array = sortTest.createArray();
System.out.println("==========快速排序後(正序)==========");
sortTest.quickSort(array, "asc");
sortTest.printArray(array);
System.out.println("==========快速排序後(倒序)==========");
sortTest.quickSort(array, "desc");
sortTest.printArray(array);
System.out.println("==========數組二分查找==========");
System.out.println("您要找的數在第" + sortTest.binarySearch(array, 74) + "個位子。(下標從0計算)");
}
}
字元串排序:
public class StringSort {
public static void main(String []args) {
String[] s={"a","b","c","d","m","f"};
for(int i=s.length-1;i>=1;i--){
for(int j=0;j<=i-1;j++) {
if(s[j].compareTo(s[j+1])<0) {
String temp=null;
temp=s[j];
s[j]=s[j+1];
s[j+1]=temp;
}
}
}
for(String a:s){
System.out.print(a+" ");
}
}
}
比較字元串的實質是比較字元串的字母,首字母相同,比較下一個,然後又相同的話,再下一個....所以你可以先用substring();截出第一個字元,然後再比較,相同的再截第二個,.....
hope some help for you
F. 如何理解java數據結構中的快速排序方法
原理:
快速排序也是分治法思想的一種實現,他的思路是使數組中的每個元素與基準值(Pivot,通常是數組的首個值,A[0])比較,數組中比基準值小的放在基準值的左邊,形成左部;大的放在右邊,形成右部;接下來將左部和右部分別遞歸地執行上面的過程:選基準值,小的放在左邊,大的放在右邊。。。直到排序結束。
步驟:
1.找基準值,設Pivot = a[0]
2.分區(Partition):比基準值小的放左邊,大的放右邊,基準值(Pivot)放左部與右部的之間。
3.進行左部(a[0] - a[pivot-1])的遞歸,以及右部(a[pivot+1] - a[n-1])的遞歸,重復上述步驟。
排序效果:
G. 請教 java 分治法求最小子數組和
這是分治求最大子數組和
首先重要點是:遞歸,這個是關鍵,何為遞歸,就是自己調用自己,比如這個代碼中的helper方法,就是遞歸,該代碼運行時,會自己調用自己很多次,數組就會兩分,兩分再兩分,這樣就會把大的問題分解成小的問題,最後把小的問題匯集起來得到答案。
你表達不出的東西和沒理解的就是這個遞歸,別小看這個遞歸,這是本代碼的關鍵點,最重要的部分。
H. 數據結構 java開發中常用的排序演算法有哪些
排序演算法有很多,所以在特定情景中使用哪一種演算法很重要。為了選擇合適的演算法,可以按照建議的順序考慮以下標准:
(1)執行時間
(2)存儲空間
(3)編程工作
對於數據量較小的情形,(1)(2)差別不大,主要考慮(3);而對於數據量大的,(1)為首要。
主要排序法有:
一、冒泡(Bubble)排序——相鄰交換
二、選擇排序——每次最小/大排在相應的位置
三、插入排序——將下一個插入已排好的序列中
四、殼(Shell)排序——縮小增量
五、歸並排序
六、快速排序
七、堆排序
八、拓撲排序
一、冒泡(Bubble)排序
----------------------------------Code 從小到大排序n個數------------------------------------
void BubbleSortArray()
{
for(int i=1;i<n;i++)
{
for(int j=0;i<n-i;j++)
{
if(a[j]>a[j+1])//比較交換相鄰元素
{
int temp;
temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
}
}
}
}
-------------------------------------------------Code------------------------------------------------
效率 O(n²),適用於排序小列表。
二、選擇排序
----------------------------------Code 從小到大排序n個數--------------------------------
void SelectSortArray()
{
int min_index;
for(int i=0;i<n-1;i++)
{
min_index=i;
for(int j=i+1;j<n;j++)//每次掃描選擇最小項
if(arr[j]<arr[min_index]) min_index=j;
if(min_index!=i)//找到最小項交換,即將這一項移到列表中的正確位置
{
int temp;
temp=arr[i]; arr[i]=arr[min_index]; arr[min_index]=temp;
}
}
}
-------------------------------------------------Code-----------------------------------------
效率O(n²),適用於排序小的列表。
三、插入排序
--------------------------------------------Code 從小到大排序n個數-------------------------------------
void InsertSortArray()
{
for(int i=1;i<n;i++)//循環從第二個數組元素開始,因為arr[0]作為最初已排序部分
{
int temp=arr[i];//temp標記為未排序第一個元素
int j=i-1;
while (j>=0 && arr[j]>temp)/*將temp與已排序元素從小到大比較,尋找temp應插入的位置*/
{
arr[j+1]=arr[j];
j--;
}
arr[j+1]=temp;
}
}
------------------------------Code--------------------------------------------------------------
最佳效率O(n);最糟效率O(n²)與冒泡、選擇相同,適用於排序小列表
若列表基本有序,則插入排序比冒泡、選擇更有效率。
四、殼(Shell)排序——縮小增量排序
-------------------------------------Code 從小到大排序n個數-------------------------------------
void ShellSortArray()
{
for(int incr=3;incr<0;incr--)//增量遞減,以增量3,2,1為例
{
for(int L=0;L<(n-1)/incr;L++)//重復分成的每個子列表
{
for(int i=L+incr;i<n;i+=incr)//對每個子列表應用插入排序
{
int temp=arr[i];
int j=i-incr;
while(j>=0&&arr[j]>temp)
{
arr[j+incr]=arr[j];
j-=incr;
}
arr[j+incr]=temp;
}
}
}
}
--------------------------------------Code-------------------------------------------
適用於排序小列表。
效率估計O(nlog2^n)~O(n^1.5),取決於增量值的最初大小。建議使用質數作為增量值,因為如果增量值是2的冪,則在下一個通道中會再次比較相同的元素。
殼(Shell)排序改進了插入排序,減少了比較的次數。是不穩定的排序,因為排序過程中元素可能會前後跳躍。
五、歸並排序
----------------------------------------------Code 從小到大排序---------------------------------------
void MergeSort(int low,int high)
{
if(low>=high) return;//每個子列表中剩下一個元素時停止
else int mid=(low+high)/2;/*將列表劃分成相等的兩個子列表,若有奇數個元素,則在左邊子列表大於右側子列表*/
MergeSort(low,mid);//子列表進一步劃分
MergeSort(mid+1,high);
int [] B=new int [high-low+1];//新建一個數組,用於存放歸並的元素
for(int i=low,j=mid+1,k=low;i<=mid && j<=high;k++)/*兩個子列表進行排序歸並,直到兩個子列表中的一個結束*/
{
if (arr[i]<=arr[j];)
{
B[k]=arr[i];
I++;
}
else
{ B[k]=arr[j]; j++; }
}
for( ;j<=high;j++,k++)//如果第二個子列表中仍然有元素,則追加到新列表
B[k]=arr[j];
for( ;i<=mid;i++,k++)//如果在第一個子列表中仍然有元素,則追加到新列表中
B[k]=arr[i];
for(int z=0;z<high-low+1;z++)//將排序的數組B的 所有元素復制到原始數組arr中
arr[z]=B[z];
}
-----------------------------------------------------Code---------------------------------------------------
效率O(nlogn),歸並的最佳、平均和最糟用例效率之間沒有差異。
適用於排序大列表,基於分治法。
六、快速排序
------------------------------------Code--------------------------------------------
/*快速排序的演算法思想:選定一個樞紐元素,對待排序序列進行分割,分割之後的序列一個部分小於樞紐元素,一個部分大於樞紐元素,再對這兩個分割好的子序列進行上述的過程。*/ void swap(int a,int b){int t;t =a ;a =b ;b =t ;}
int Partition(int [] arr,int low,int high)
{
int pivot=arr[low];//採用子序列的第一個元素作為樞紐元素
while (low < high)
{
//從後往前栽後半部分中尋找第一個小於樞紐元素的元素
while (low < high && arr[high] >= pivot)
{
--high;
}
//將這個比樞紐元素小的元素交換到前半部分
swap(arr[low], arr[high]);
//從前往後在前半部分中尋找第一個大於樞紐元素的元素
while (low <high &&arr [low ]<=pivot )
{
++low ;
}
swap (arr [low ],arr [high ]);//將這個樞紐元素大的元素交換到後半部分
}
return low ;//返回樞紐元素所在的位置
}
void QuickSort(int [] a,int low,int high)
{
if (low <high )
{
int n=Partition (a ,low ,high );
QuickSort (a ,low ,n );
QuickSort (a ,n +1,high );
}
}
----------------------------------------Code-------------------------------------
平均效率O(nlogn),適用於排序大列表。
此演算法的總時間取決於樞紐值的位置;選擇第一個元素作為樞紐,可能導致O(n²)的最糟用例效率。若數基本有序,效率反而最差。選項中間值作為樞紐,效率是O(nlogn)。
基於分治法。
七、堆排序
最大堆:後者任一非終端節點的關鍵字均大於或等於它的左、右孩子的關鍵字,此時位於堆頂的節點的關鍵字是整個序列中最大的。
思想:
(1)令i=l,並令temp= kl ;
(2)計算i的左孩子j=2i+1;
(3)若j<=n-1,則轉(4),否則轉(6);
(4)比較kj和kj+1,若kj+1>kj,則令j=j+1,否則j不變;
(5)比較temp和kj,若kj>temp,則令ki等於kj,並令i=j,j=2i+1,並轉(3),否則轉(6)
(6)令ki等於temp,結束。
-----------------------------------------Code---------------------------
void HeapSort(SeqIAst R)
{ //對R[1..n]進行堆排序,不妨用R[0]做暫存單元 int I; BuildHeap(R); //將R[1-n]建成初始堆for(i=n;i>1;i--) //對當前無序區R[1..i]進行堆排序,共做n-1趟。{ R[0]=R[1]; R[1]=R[i]; R[i]=R[0]; //將堆頂和堆中最後一個記錄交換 Heapify(R,1,i-1); //將R[1..i-1]重新調整為堆,僅有R[1]可能違反堆性質 } } ---------------------------------------Code--------------------------------------
堆排序的時間,主要由建立初始堆和反復重建堆這兩部分的時間開銷構成,它們均是通過調用Heapify實現的。
堆排序的最壞時間復雜度為O(nlgn)。堆排序的平均性能較接近於最壞性能。 由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的文件。 堆排序是就地排序,輔助空間為O(1), 它是不穩定的排序方法。
堆排序與直接插入排序的區別:
直接選擇排序中,為了從R[1..n]中選出關鍵字最小的記錄,必須進行n-1次比較,然後在R[2..n]中選出關鍵字最小的記錄,又需要做n-2次比較。事實上,後面的n-2次比較中,有許多比較可能在前面的n-1次比較中已經做過,但由於前一趟排序時未保留這些比較結果,所以後一趟排序時又重復執行了這些比較操作。
堆排序可通過樹形結構保存部分比較結果,可減少比較次數。
八、拓撲排序
例 :學生選修課排課先後順序
拓撲排序:把有向圖中各頂點按照它們相互之間的優先關系排列成一個線性序列的過程。
方法:
在有向圖中選一個沒有前驅的頂點且輸出
從圖中刪除該頂點和所有以它為尾的弧
重復上述兩步,直至全部頂點均已輸出(拓撲排序成功),或者當圖中不存在無前驅的頂點(圖中有迴路)為止。
---------------------------------------Code--------------------------------------
void TopologicalSort()/*輸出拓撲排序函數。若G無迴路,則輸出G的頂點的一個拓撲序列並返回OK,否則返回ERROR*/
{
int indegree[M];
int i,k,j;
char n;
int count=0;
Stack thestack;
FindInDegree(G,indegree);//對各頂點求入度indegree[0....num]
InitStack(thestack);//初始化棧
for(i=0;i<G.num;i++)
Console.WriteLine("結點"+G.vertices[i].data+"的入度為"+indegree[i]);
for(i=0;i<G.num;i++)
{
if(indegree[i]==0)
Push(thestack.vertices[i]);
}
Console.Write("拓撲排序輸出順序為:");
while(thestack.Peek()!=null)
{
Pop(thestack.Peek());
j=locatevex(G,n);
if (j==-2)
{
Console.WriteLine("發生錯誤,程序結束。");
exit();
}
Console.Write(G.vertices[j].data);
count++;
for(p=G.vertices[j].firstarc;p!=NULL;p=p.nextarc)
{
k=p.adjvex;
if (!(--indegree[k]))
Push(G.vertices[k]);
}
}
if (count<G.num)
Cosole.WriteLine("該圖有環,出現錯誤,無法排序。");
else
Console.WriteLine("排序成功。");
}
----------------------------------------Code--------------------------------------
演算法的時間復雜度O(n+e)。
I. 用Java採用分治法遞歸求最大值和最小值,產生死循環
DEBUG了一下才看出來,遞歸坑人啊。。。
也建議你用DEBUG跟蹤一下。。
首先這里遞歸了幾次
float rmax = 0, rmin = 0, bmax = 0, bmin = 0;
mid = (i + j) / 2;
maxMin(i, mid, a, rmax, rmin);
當i=0,mid=1的時候,上面幾行代碼的最後一行執行完成,並輸出了最大最小值。
之後這個一行執行完了繼續往下執行,造成死循環
即i=2,j=1
J. java怎麼實現排序
Java實現幾種常見排序方法
日常操作中常見的排序方法有:冒泡排序、快速排序、選擇排序、插入排序、希爾排序,甚至還有基數排序、雞尾酒排序、桶排序、鴿巢排序、歸並排序等。
以下常見演算法的定義
1. 插入排序:插入排序基本操作就是將一個數據插入到已經排好序的有序數據中,從而得到一個新的、個數加一的有序數據,演算法適用於少量數據的排序,時間復雜度為O(n^2)。是穩定的排序方法。插入排序的基本思想是:每步將一個待排序的紀錄,按其關鍵碼值的大小插入前面已經排序的文件中適當位置上,直到全部插入完為止。
2. 選擇排序:選擇排序(Selection sort)是一種簡單直觀的排序演算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。 選擇排序是不穩定的排序方法。
3. 冒泡排序:冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序演算法。它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個演算法的名字由來是因為越大的元素會經由交換慢慢「浮」到數列的頂端。
4. 快速排序:快速排序(Quicksort)是對冒泡排序的一種改進。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
5. 歸並排序:歸並排序是建立在歸並操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為二路歸並。
6. 希爾排序:希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。希爾排序是非穩定排序演算法。希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,演算法便終止。
https://www.cnblogs.com/wangmingshun/p/5635292.html