下面給你介紹四種常用排序演算法:
1、冒泡排序
特點:效率低,實現簡單
思想(從小到大排):每一趟將待排序序列中最大元素移到最後,剩下的為新的待排序序列,重復上述步驟直到排完所有元素。這只是冒泡排序的一種,當然也可以從後往前排。
B. 數據結構 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)。
C. 在java中,給出一個數組,裡面有重復的數字,要求將重復的數字去掉然後給新的數組進行排序
數組是沒有去重的函數的,你可以用set或者map來去重 ,如果你想要代碼,可以追問
D. 用java讀取txt文件,然後對數據進行排序,去重等操作。
因為各氏姿個列沒有分隔符,我添加了逗顫段號作分隔符.文件內容如下.
Id Name Year Current Cumulative
16, Melissa Will, 3, 5, 9
17, Naomi Thomas, 3, 3, 12
21, Ronaldo Gomes, 3, 1, 11
22, Sam Del-Prete, 2, 4, 10
2, Abe Storey, 3, 4, 6
3, Anthony Tabrin, 3, 1, 7
18, Nathan Bentley, 3, 2, 19
你用這個文件內容,試一下下邊的程序.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("H:\\test.txt");
BufferedReader br = new BufferedReader(fr);
int row = 1;
int sum1 = 0, sum2 = 0;
FileWriter fw = new FileWriter("H:\\new.txt");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("Id Name Year Current Cumulative");
bw.newLine();
List<String> first = new ArrayList<String>();
while (br.ready()) {
if (row++ == 1) {
br.readLine();
continue;
}
String line = br.readLine();
String[] array = line.split(",", 5);
String tmp = array[1].trim().substring(0, 1);
if (!first.contains(tmp)) {
sum1 += toInt(array[3].trim());
sum2 += toInt(array[4].trim());
bw.write(line);
bw.newLine();
first.add(tmp);
}
}
bw.write("sum : \t\t\t\t" + sum1 + "\殲洞絕t" + sum2);
bw.newLine();
bw.write("average : \t\t\t" + (sum1 / (first.size() * 1.0)) + "\t"
+ sum2 / (first.size() * 1.0));
br.close();
fr.close();
bw.close();
fw.close();
}
public static int toInt(String str) {
try {
return Integer.parseInt(str);
} catch (Exception e) {
return 0;
}
}
}
E. JAVA數組去重問題
我這有個笨辦法供樓主參考:
把vector中元素都取出來放到一個數組中,
根據數據的實際情況,
選擇不同的時間復雜度為log2N的排序演算法進行排序,
然後新建一個鏈表,
結點為保存數據和頻率的類,
遍歷排序後的數組,
如果鏈表的尾結點與數組中當前元素相同,
將尾結點的頻率加1,
否則append一個頻率為1的結點,
希望大牛們能給出更好的解法
F. java排列組合的演算法 譬如我有(A,B,C,D),我想輸出的結果是
我覺得可以看成數字的排列如 1 2 3 4分別代表A B C D
就是將1 2 3 4排列
四位的就是1234
三位的就是從這四個數字中取出三個數字,得到的三位數是最小的,如:
取 1 2 3 可以得到123 213 321 132等等 其中123是最小的
兩為數字的跟三位數字的一樣
G. java對List去重並排序,如何快速地去掉兩個
Java8開始,對數值,集昌並廳合等提供了Stream流操作,可以方便的對集合進行操作.
比如 篩選,過濾,去重, 映射, 排序,規約,收集 等操作
簡單的參考代碼如下
importjava.util.Arrays;
importjava.util.List;
importjava.util.stream.Collectors;
//使用Java8的Stream特性和Java8的Lambda語句
publicclassDemo{
publicstaticvoidmain(String[]args){
//需求:集合去重,排序,得到一個新集耐隱合裡面的元素是之前元素的平方
List<Integer>list=Arrays.asList(5,2,2,1,3,4);
List<Integer>listResult= list
.stream()//得到流
.distinct()//去重蔽爛5,2,1,3,4
.sorted()//自然排序,也可以自定義排序規則1,2,3,4,5
.map(x->x*x)//每個元素求平方1,4,9,16,25
.collect(Collectors.toList());//收集並返回
System.out.println(listResult);//1,4,9,16,25
}
}
H. java面試題:將一個20G的數據,存入一個運行2G的電腦里,每個數據佔一行,怎麼去重
這題考的是大數據去重,數據量大於內存,即無法直接在內存中去重,那麼有兩個方案:
1、內存外去重
也就是將數據存入數據顫蘆庫,然後利用資料庫進行排序並去重。
優缺點:
1)優點:簡單直接
2)茄羨帶缺點:消派空耗大
2、演算法去重
題目中說明是20G數據,假設每行數據是1k,則數據行數是20M(如果每行數據是512位元組,則數據行數是40M),可使用MD5對每行數據進行映射,獲得16位元組映射嗎,即總共需要內存空間320M(或640M),滿足內存內去重的需求。
優缺點:
1)優點:在內存內進行處理,速度明顯比內存為要快。
2)缺點:需要進行額外的編碼,程序復雜度和效率要求較高。
I. JAVA關於順序數組數據去重,效率最高的方式是什麼
JAVA關於順序數組數據去重,效率最高的方式是使用LinkedHashSet也是Set,set的特徵就是對重復的元素只保存一個,LinkedHashSet只是在內仿納埋部使用鏈表維護元素插入的順序
packagecom.question;
importjava.io.BufferedReader;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.io.OutputStream;
importjava.util.LinkedHashSet;
/**
*deletetheconflictString.
*
*@authorXxx
*/
publicclassQ16{
/**
*generatethetext.
*
*/
publicvoidinit(){
//writefile
OutputStreamoutputStream=null;
try{
outputStream=newFileOutputStream("C:/init.txt");
for(inti=0;i<100000;i++){
for(intj=0;j<2;j++){
outputStream.write(("Hello"+i).getBytes());
outputStream.write(" ".getBytes());
}
}
}catch(FileNotFoundExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}finally{
if(outputStream!=null){
outputStream=null;
}
}
}
/**
*filterthestring.
*
*@return
*/
publicLinkedHashSet<String>filter(){
//createaLinkedHashSetproject.
LinkedHashSet<String>linkedHashSet=newLinkedHashSet<String>();
try{
//readthefile.
InputStreaminputStream=newFileInputStream("C:/init.txt");
=newInputStreamReader(inputStream);
BufferedReaderbufferedReader=newBufferedReader(inputStreamReader);
Stringline=bufferedReader.readLine();
備螞//
while(line!=null){
linkedHashSet.add(line);
line=bufferedReader.readLine();
}
}catch(FileNotFoundExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
茄慧}
//returntheresult.
returnlinkedHashSet;
}
@Deprecated
publicstaticvoidmain(String[]args){
Q16q16=newQ16();
//q16.init();
LinkedHashSet<String>linkedHashSet=q16.filter();
System.out.println(linkedHashSet.size());
}
}
J. 有序數組去重的幾種演算法
這個問題的意思是,如果假設一個數組中存蘆豎在重復的數據項,那麼就中保留重復數據項中的一個。也就是說最終輸出的結果數組中不容許存在重復數據項,所以因為這里涉及到重復數據項的問題,所以立馬想到了集合(Set)這個數據結構,因為它是不容序存在重復數據項的數據結構,
思路1.也就是將數組中的所有元素插入到一個Set中,利用Set的自動剔除重復數據項的功能,將導致所有重復數據項慎胡沒有辦法插入成功,也就是add方法
返回false,然後調用toArray方法,返回這個集合所對應的數組。那麼這個數組就是一個沒有重復數據項的數組,利用這個方法,通過比較結果數組和
源數組之間的大小,查看源數組中到底是否存在重復數陪孝大據項。
思路2.除了利用Set這個數據結構不容序存在重復數據項的功能之外,還有一種很容易想到的方法,也就是對整個數組進行排序,然後遍歷排序之後的數組,將重復數據項,清除掉。
思路1的實現:
public static int[] noDup(int[] array) {
Set<Integer> set = new
HashSet<Integer>();
for (int i :
array)
set.add(i);
Integer[]
integers = (Integer[]) set.toArray();
int[] result
= new int[integers.length];
for (int i =
0; i < integers.length; i++)
result[i] =
integers[i];
return
result;
}
思路2的實現:
使用快速排序等演算法對數組進行排序,這個排序過程不在介紹。假設下面這個演算法的輸入是一個幾經排好序的數組。
for (int i = 0; i < array.length - 1; i++) {
if (array[i]
== array[i + 1]) {
array[i] =
-1;
}
}
通過上面這段代碼就能夠實現把數組中所有的重復數據項只保留一個,其它的置為-1或者根據實際情況置成其它值。然後遍歷數據,刪除所有位-1的數據項,並且將數組中包含的記錄個數不斷減少即可。