public class Arr{
創(chuàng)新互聯(lián)成立與2013年,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都做網(wǎng)站、成都網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元老河口做網(wǎng)站,已為上家服務(wù),為老河口各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575
//數(shù)組
int[] arr = {3,1,6,4,5,10,2};
//對(duì)數(shù)組進(jìn)行簡(jiǎn)單的排序
java.util.Arrays.sort(arr);
//輸出最大值、最小值
System.out.println("最大值:" + arr[arr.length-1] +"\n最小值:" + arr[0]);
//從小到大輸出
System.out.println(java.util.Arrays.toString(arr));
}
額。。程序最后多打了一個(gè)大括號(hào)
這段代碼的功能是對(duì)一個(gè)有向圖進(jìn)行拓?fù)渑判?,若有環(huán)則拋出異常
首先要明白拓?fù)渑判蚴亲鍪裁吹模斠姲俣劝倏?-拓?fù)渑判颍ㄓ袌D有樣例)
然后說這段代碼:
通過將圖中入度為0的點(diǎn)存入隊(duì)列,用隊(duì)首的點(diǎn)去查找與此點(diǎn)連接且入度為1的點(diǎn),
把找到的點(diǎn)在存入隊(duì)列,令這隊(duì)首的點(diǎn)出隊(duì)。如此至到找不到入度為0的點(diǎn),結(jié)束while
循環(huán),最后再判斷進(jìn)入再離開隊(duì)列的點(diǎn)的個(gè)數(shù)若小于圖中總點(diǎn)數(shù),則判定有環(huán)。
注:可以根據(jù)注釋判斷函數(shù)功能
void Graph::topsort()
{
QueueVertex q;//定義存儲(chǔ)點(diǎn)的信息的隊(duì)列,由于是偽代碼,信息類型不詳,一般是該點(diǎn)在題目中的編號(hào)
int counter=0;//記錄當(dāng)前有幾個(gè)點(diǎn)已經(jīng)出隊(duì)了
q.makeEmpty();//初始化隊(duì)列,令其清空
for each Vertex v //初始化查找入度為0的點(diǎn),若找到則入隊(duì)
if(v.indegree==0) //判斷入度為0
q.enqueue(v); //入隊(duì)
while(!q.isEmpty()) //若隊(duì)列不為空則一直循環(huán)
{
Vertex v=q.dequeue(); //隊(duì)首點(diǎn)出隊(duì)
v.topNum=++counter; //累加出隊(duì)點(diǎn)數(shù)
for each Vertex w adjacent to v //用此出隊(duì)點(diǎn),即剛才的隊(duì)首,查找僅與其相連的點(diǎn),并將找到的點(diǎn)入隊(duì)
if(--w.indegree==0)
q.enqueue(w);
}
if(counter!=NUM_VERTICES) //若總出隊(duì)點(diǎn)不等于圖中總點(diǎn)數(shù),則有環(huán)
throw CycleFoudException();
}
信息工程系軟件技術(shù)學(xué)生課程表(拓?fù)渑判颍?/p>
拓?fù)鋱D為:(圖不好粘貼)
運(yùn)用拓?fù)涓拍钆判虻慕Y(jié)果:
C1 , C9 , C3 , C2 , C7 , C4, C5 , C8 , C6
C1計(jì)算機(jī)應(yīng)用基礎(chǔ) C2 C語言 C3 VB語言 C4 JSP C5數(shù)字邏輯電路 C6軟件工程
C7計(jì)算機(jī)網(wǎng)絡(luò)基礎(chǔ) C8 Java語言 C9計(jì)算機(jī)數(shù)學(xué)基礎(chǔ)
/*-------------------------------主類-----------------------------*/
public class Navy1 {
public static void main(String[] args) {
topology(); //調(diào)用拓?fù)涞臉?gòu)造方法
}
public static void topology() { //構(gòu)造拓?fù)浞椒?/p>
/**
聲明拓?fù)鋱D中的元素
定義節(jié)點(diǎn)和節(jié)點(diǎn)之間的關(guān)系
Entry(a,b)a為b的前導(dǎo)
**/
Entry[] relations = { new Entry(9, 2), new Entry(3,7),
new Entry(7, 5), new Entry(5, 8), new Entry(8, 6),
new Entry(4, 6), new Entry(1, 3), new Entry(7, 4),
new Entry(9, 5), new Entry(2, 8) };
int n = 9;
int n1 = 9;
/*計(jì)算拓?fù)鋱D中節(jié)點(diǎn)數(shù)*/
int[] count = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/*開辟內(nèi)存空間*/
Node[] top = { null, null, null, null, null, null, null, null, null, null };
Node p = null;
for (int i = 0; i relations.length; i++) {
count[relations[i].k]++;
p = new Node();
p.suc = relations[i].k;
p.next = top[relations[i].j];
top[relations[i].j] = p;
}
int r = 0;
int[] qlink = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (int i = 1; i = n; i++) {
if (count[i] == 0) {
qlink[r] = i;
r = i;
}
}
int f = qlink[0];
System.out.println("題目及要求:");
System.out.println("課程排課程序。寫一個(gè)程序,實(shí)現(xiàn)對(duì)某個(gè)專業(yè)的課程進(jìn)行排課的功能。");
System.out.println("已知某專業(yè)的課程和它們的前導(dǎo)和后續(xù)關(guān)系(以有向圖的形式表示),");
System.out.println("請(qǐng)用拓?fù)渑判蛩惴ㄇ蟪鲞@些課程的優(yōu)先關(guān)系并輸出一種排課結(jié)果");
System.out.println("--------------------------------------");
System.out.println("08信息工程系軟件技術(shù)課程表(拓?fù)渑判颍?);
while (true)
{
System.out.println(f);
if (f == 0) //結(jié)束條件
{
break;
}
else
{
n1--;
p = top[f];
while (true)
{
if (p == null)
{
break;
}
else
{
count[p.suc]--;
if (count[p.suc] == 0)
{
qlink[r] = p.suc;
r = p.suc;
}
p = p.next;
}
}
f = qlink[f];
}
}
System.out.println("結(jié)束的標(biāo)志為:" + n1);
System.out.println("--------------------------------------------");
System.out.println("注釋(數(shù)字對(duì)應(yīng)的課程):");
System.out.println("1 計(jì)算機(jī)應(yīng)用基礎(chǔ) 2 C語言 3 VB語言 ");
System.out.println("4 JSP 5 數(shù)字邏輯電路 6 軟件工程");
System.out.println("7 計(jì)算機(jī)網(wǎng)絡(luò)基礎(chǔ) 8 Java語言 9 計(jì)算機(jī)數(shù)學(xué)基礎(chǔ)");
System.out.println("--------------------------------------------");
}
/*構(gòu)造元素類*/
private static class Entry
{
public Entry(int begin, int end) //定義開始元素和結(jié)束元素
{
this.j = begin;
this.k = end;
}
int j;
int k;
}
/*聲明節(jié)點(diǎn)的后繼*/
private static class Node
{
public Node(int suc, Node next)
{
this.suc = suc;
this.next = next;
}
public Node()
{
}
int suc;
Node next;
}
}
排序算法有很多,所以在特定情景中使用哪一種算法很重要。為了選擇合適的算法,可以按照建議的順序考慮以下標(biāo)準(zhǔn):
(1)執(zhí)行時(shí)間
(2)存儲(chǔ)空間
(3)編程工作
對(duì)于數(shù)據(jù)量較小的情形,(1)(2)差別不大,主要考慮(3);而對(duì)于數(shù)據(jù)量大的,(1)為首要。
主要排序法有:
一、冒泡(Bubble)排序——相鄰交換
二、選擇排序——每次最小/大排在相應(yīng)的位置
三、插入排序——將下一個(gè)插入已排好的序列中
四、殼(Shell)排序——縮小增量
五、歸并排序
六、快速排序
七、堆排序
八、拓?fù)渑判?/p>
一、冒泡(Bubble)排序
----------------------------------Code 從小到大排序n個(gè)數(shù)------------------------------------
void BubbleSortArray()
{
for(int i=1;in;i++)
{
for(int j=0;in-i;j++)
{
if(a[j]a[j+1])//比較交換相鄰元素
{
int temp;
temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
}
}
}
}
-------------------------------------------------Code------------------------------------------------
效率 O(n2),適用于排序小列表。
二、選擇排序
----------------------------------Code 從小到大排序n個(gè)數(shù)--------------------------------
void SelectSortArray()
{
int min_index;
for(int i=0;in-1;i++)
{
min_index=i;
for(int j=i+1;jn;j++)//每次掃描選擇最小項(xiàng)
if(arr[j]arr[min_index]) min_index=j;
if(min_index!=i)//找到最小項(xiàng)交換,即將這一項(xiàng)移到列表中的正確位置
{
int temp;
temp=arr[i]; arr[i]=arr[min_index]; arr[min_index]=temp;
}
}
}
-------------------------------------------------Code-----------------------------------------
效率O(n2),適用于排序小的列表。
三、插入排序
--------------------------------------------Code 從小到大排序n個(gè)數(shù)-------------------------------------
void InsertSortArray()
{
for(int i=1;in;i++)//循環(huán)從第二個(gè)數(shù)組元素開始,因?yàn)閍rr[0]作為最初已排序部分
{
int temp=arr[i];//temp標(biāo)記為未排序第一個(gè)元素
int j=i-1;
while (j=0 arr[j]temp)/*將temp與已排序元素從小到大比較,尋找temp應(yīng)插入的位置*/
{
arr[j+1]=arr[j];
j--;
}
arr[j+1]=temp;
}
}
------------------------------Code--------------------------------------------------------------
最佳效率O(n);最糟效率O(n2)與冒泡、選擇相同,適用于排序小列表
若列表基本有序,則插入排序比冒泡、選擇更有效率。
四、殼(Shell)排序——縮小增量排序
-------------------------------------Code 從小到大排序n個(gè)數(shù)-------------------------------------
void ShellSortArray()
{
for(int incr=3;incr0;incr--)//增量遞減,以增量3,2,1為例
{
for(int L=0;L(n-1)/incr;L++)//重復(fù)分成的每個(gè)子列表
{
for(int i=L+incr;in;i+=incr)//對(duì)每個(gè)子列表應(yīng)用插入排序
{
int temp=arr[i];
int j=i-incr;
while(j=0arr[j]temp)
{
arr[j+incr]=arr[j];
j-=incr;
}
arr[j+incr]=temp;
}
}
}
}
--------------------------------------Code-------------------------------------------
適用于排序小列表。
效率估計(jì)O(nlog2^n)~O(n^1.5),取決于增量值的最初大小。建議使用質(zhì)數(shù)作為增量值,因?yàn)槿绻隽恐凳?的冪,則在下一個(gè)通道中會(huì)再次比較相同的元素。
殼(Shell)排序改進(jìn)了插入排序,減少了比較的次數(shù)。是不穩(wěn)定的排序,因?yàn)榕判蜻^程中元素可能會(huì)前后跳躍。
五、歸并排序
----------------------------------------------Code 從小到大排序---------------------------------------
void MergeSort(int low,int high)
{
if(low=high) return;//每個(gè)子列表中剩下一個(gè)元素時(shí)停止
else int mid=(low+high)/2;/*將列表劃分成相等的兩個(gè)子列表,若有奇數(shù)個(gè)元素,則在左邊子列表大于右側(cè)子列表*/
MergeSort(low,mid);//子列表進(jìn)一步劃分
MergeSort(mid+1,high);
int [] B=new int [high-low+1];//新建一個(gè)數(shù)組,用于存放歸并的元素
for(int i=low,j=mid+1,k=low;i=mid j=high;k++)/*兩個(gè)子列表進(jìn)行排序歸并,直到兩個(gè)子列表中的一個(gè)結(jié)束*/
{
if (arr[i]=arr[j];)
{
B[k]=arr[i];
I++;
}
else
{ B[k]=arr[j]; j++; }
}
for( ;j=high;j++,k++)//如果第二個(gè)子列表中仍然有元素,則追加到新列表
B[k]=arr[j];
for( ;i=mid;i++,k++)//如果在第一個(gè)子列表中仍然有元素,則追加到新列表中
B[k]=arr[i];
for(int z=0;zhigh-low+1;z++)//將排序的數(shù)組B的 所有元素復(fù)制到原始數(shù)組arr中
arr[z]=B[z];
}
-----------------------------------------------------Code---------------------------------------------------
效率O(nlogn),歸并的最佳、平均和最糟用例效率之間沒有差異。
適用于排序大列表,基于分治法。
六、快速排序
------------------------------------Code--------------------------------------------
/*快速排序的算法思想:選定一個(gè)樞紐元素,對(duì)待排序序列進(jìn)行分割,分割之后的序列一個(gè)部分小于樞紐元素,一個(gè)部分大于樞紐元素,再對(duì)這兩個(gè)分割好的子序列進(jìn)行上述的過程。*/ 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];//采用子序列的第一個(gè)元素作為樞紐元素
while (low high)
{
//從后往前栽后半部分中尋找第一個(gè)小于樞紐元素的元素
while (low high arr[high] = pivot)
{
--high;
}
//將這個(gè)比樞紐元素小的元素交換到前半部分
swap(arr[low], arr[high]);
//從前往后在前半部分中尋找第一個(gè)大于樞紐元素的元素
while (low high arr [low ]=pivot )
{
++low ;
}
swap (arr [low ],arr [high ]);//將這個(gè)樞紐元素大的元素交換到后半部分
}
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),適用于排序大列表。
此算法的總時(shí)間取決于樞紐值的位置;選擇第一個(gè)元素作為樞紐,可能導(dǎo)致O(n2)的最糟用例效率。若數(shù)基本有序,效率反而最差。選項(xiàng)中間值作為樞紐,效率是O(nlogn)。
基于分治法。
七、堆排序
最大堆:后者任一非終端節(jié)點(diǎn)的關(guān)鍵字均大于或等于它的左、右孩子的關(guān)鍵字,此時(shí)位于堆頂?shù)墓?jié)點(diǎn)的關(guān)鍵字是整個(gè)序列中最大的。
思想:
(1)令i=l,并令temp= kl ;
(2)計(jì)算i的左孩子j=2i+1;
(3)若j=n-1,則轉(zhuǎn)(4),否則轉(zhuǎn)(6);
(4)比較kj和kj+1,若kj+1kj,則令j=j(luò)+1,否則j不變;
(5)比較temp和kj,若kjtemp,則令ki等于kj,并令i=j,j=2i+1,并轉(zhuǎn)(3),否則轉(zhuǎn)(6)
(6)令ki等于temp,結(jié)束。
-----------------------------------------Code---------------------------
void HeapSort(SeqIAst R)
{ //對(duì)R[1..n]進(jìn)行堆排序,不妨用R[0]做暫存單元 int I; BuildHeap(R); //將R[1-n]建成初始堆for(i=n;i1;i--) //對(duì)當(dāng)前無序區(qū)R[1..i]進(jìn)行堆排序,共做n-1趟。{ R[0]=R[1]; R[1]=R[i]; R[i]=R[0]; //將堆頂和堆中最后一個(gè)記錄交換 Heapify(R,1,i-1); //將R[1..i-1]重新調(diào)整為堆,僅有R[1]可能違反堆性質(zhì) } } ---------------------------------------Code--------------------------------------
堆排序的時(shí)間,主要由建立初始堆和反復(fù)重建堆這兩部分的時(shí)間開銷構(gòu)成,它們均是通過調(diào)用Heapify實(shí)現(xiàn)的。
堆排序的最壞時(shí)間復(fù)雜度為O(nlgn)。堆排序的平均性能較接近于最壞性能。 由于建初始堆所需的比較次數(shù)較多,所以堆排序不適宜于記錄數(shù)較少的文件。 堆排序是就地排序,輔助空間為O(1), 它是不穩(wěn)定的排序方法。
堆排序與直接插入排序的區(qū)別:
直接選擇排序中,為了從R[1..n]中選出關(guān)鍵字最小的記錄,必須進(jìn)行n-1次比較,然后在R[2..n]中選出關(guān)鍵字最小的記錄,又需要做n-2次比較。事實(shí)上,后面的n-2次比較中,有許多比較可能在前面的n-1次比較中已經(jīng)做過,但由于前一趟排序時(shí)未保留這些比較結(jié)果,所以后一趟排序時(shí)又重復(fù)執(zhí)行了這些比較操作。
堆排序可通過樹形結(jié)構(gòu)保存部分比較結(jié)果,可減少比較次數(shù)。
八、拓?fù)渑判?/p>
例 :學(xué)生選修課排課先后順序
拓?fù)渑判颍喊延邢驁D中各頂點(diǎn)按照它們相互之間的優(yōu)先關(guān)系排列成一個(gè)線性序列的過程。
方法:
在有向圖中選一個(gè)沒有前驅(qū)的頂點(diǎn)且輸出
從圖中刪除該頂點(diǎn)和所有以它為尾的弧
重復(fù)上述兩步,直至全部頂點(diǎn)均已輸出(拓?fù)渑判虺晒Γ?,或者?dāng)圖中不存在無前驅(qū)的頂點(diǎn)(圖中有回路)為止。
---------------------------------------Code--------------------------------------
void TopologicalSort()/*輸出拓?fù)渑判蚝瘮?shù)。若G無回路,則輸出G的頂點(diǎn)的一個(gè)拓?fù)湫蛄胁⒎祷豋K,否則返回ERROR*/
{
int indegree[M];
int i,k,j;
char n;
int count=0;
Stack thestack;
FindInDegree(G,indegree);//對(duì)各頂點(diǎn)求入度indegree[0....num]
InitStack(thestack);//初始化棧
for(i=0;iG.num;i++)
Console.WriteLine("結(jié)點(diǎn)"+G.vertices[i].data+"的入度為"+indegree[i]);
for(i=0;iG.num;i++)
{
if(indegree[i]==0)
Push(thestack.vertices[i]);
}
Console.Write("拓?fù)渑判蜉敵鲰樞驗(yàn)椋?);
while(thestack.Peek()!=null)
{
Pop(thestack.Peek());
j=locatevex(G,n);
if (j==-2)
{
Console.WriteLine("發(fā)生錯(cuò)誤,程序結(jié)束。");
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 (countG.num)
Cosole.WriteLine("該圖有環(huán),出現(xiàn)錯(cuò)誤,無法排序。");
else
Console.WriteLine("排序成功。");
}
----------------------------------------Code--------------------------------------
算法的時(shí)間復(fù)雜度O(n+e)。