数据结构各种排序算法总结

时间:2024.3.31

数据结构各种排序算法总结

计算机排序与人进行排序的不同:计算机程序不能象人一样通览所有的数据,只能根据计算机的"比较"原理,在同一时间内对两个队员进行比较,这是算法的一种"短视"。

1. 冒泡排序 BubbleSort

最简单的一个

public void bubbleSort()

{

int out, in;

for(out=nElems-1; out>0; out--) // outer loop (backward)

for(in=0; in<out; in++) // inner loop (forward)

if( a[in] > a[in+1] ) // out of order?

swap(in, in+1); // swap them

} // end bubbleSort()

效率:O(N2)

2. 选择排序 selectSort

public void selectionSort()

{

int out, in, min;

for(out=0; out<nElems-1; out++) // outer loop

{

min = out; // minimum

for(in=out+1; in<nElems; in++) // inner loop

if(a[in] < a[min] ) // if min greater,

min = in; // we have a new min

swap(out, min); // swap them

} // end for(out)

} // end selectionSort()

效率:O(N2)

3. 插入排序 insertSort

在插入排序中,一组数据在某个时刻实局部有序的,为在冒泡和选择排序中实完全有序的。 public void insertionSort()

{

int in, out;

for(out=1; out<nElems; out++) // out is dividing line

{

long temp = a[out]; // remove marked item

in = out; // start shifts at out

while(in>0 && a[in-1] >= temp) // until one is smaller,

{

a[in] = a[in-1]; // shift item to right

--in; // go left one position

}

a[in] = temp; // insert marked item

} // end for

} // end insertionSort()

效率:比冒泡排序快一倍,比选择排序略快,但也是O(N2)

如果数据基本有序,几乎需要O(N)的时间

4. 归并排序 mergeSort

利用递归,不断的分割数组,然后归并有序数组

效率为O(N*logN),缺点是需要在存储器中有一个大小等于被排序的数据项数目的数组。 public void mergeSort() // called by main()

{ // provides workspace

long[] workSpace = new long[nElems];

recMergeSort(workSpace, 0, nElems-1);

}

//-----------------------------------------------------------

private void recMergeSort(long[] workSpace, int lowerBound,

int upperBound) {

if(lowerBound == upperBound) // if range is 1, return; // no use sorting else

{ // find midpoint int mid = (lowerBound+upperBound) / 2;

// sort low half recMergeSort(workSpace, lowerBound, mid);

// sort high half recMergeSort(workSpace, mid+1, upperBound);

// merge them merge(workSpace, lowerBound, mid+1, upperBound); } // end else

} // end recMergeSort()

//-----------------------------------------------------------

private void merge(long[] workSpace, int lowPtr,

int highPtr, int upperBound)

{

int j = 0; // workspace index int lowerBound = lowPtr;

int mid = highPtr-1;

int n = upperBound-lowerBound+1; // # of items while(lowPtr <= mid && highPtr <= upperBound)

if( theArray[lowPtr] < theArray[highPtr] )

workSpace[j++] = theArray[lowPtr++];

else

workSpace[j++] = theArray[highPtr++];

while(lowPtr <= mid)

workSpace[j++] = theArray[lowPtr++];

while(highPtr <= upperBound)

workSpace[j++] = theArray[highPtr++];

for(j=0; j<n; j++)

theArray[lowerBound+j] = workSpace[j];

} // end merge()

5. 希尔排序 ShellSort

public void shellSort()

{

int inner, outer;

long temp;

int h = 1; // find initial value of h while(h <= nElems/3)

h = h*3 + 1; // (1, 4, 13, 40, 121, ...) while(h>0) // decreasing h, until h=1 {

// h-sort the file for(outer=h; outer<nElems; outer++)

{

temp = theArray[outer];

inner = outer;

// one subpass (eg 0, 4, 8) while(inner > h-1 && theArray[inner-h] >= temp) {

theArray[inner] = theArray[inner-h];

inner -= h;

}

theArray[inner] = temp;

} // end for

h = (h-1) / 3; // decrease h

} // end while(h>0)

} // end shellSort()

希尔排序是基于插入排序的,由于插入排序复制的次数太多,导致效率的下降,而ShellSort先利用n-增量排序将数据变为基本有序,然后在利用插入排序(1-增量排序)。 n在排序中的一系列取值方法:Lnuth序列,间隔h=3h + 1

效率:O(N3/2) 到O(N7/6)

6. 快速排序

其根本机制在于划分:划分数据就是把数据分为两组,使所有关键字大于特定值的数据项在一组,使所有关键字小于特定值的数据项在另一组。

public int partitionIt(int left, int right, long pivot)

{

int leftPtr = left - 1; // right of first elem

int rightPtr = right + 1; // left of pivot

while(true)

{

while(leftPtr < right && // find bigger item

theArray[++leftPtr] < pivot)

; // (nop)

while(rightPtr > left && // find smaller item

theArray[--rightPtr] > pivot)

; // (nop)

if(leftPtr >= rightPtr) // if pointers cross,

break; // partition done

else // not crossed, so

swap(leftPtr, rightPtr); // swap elements

} // end while(true)

return leftPtr; // return partition

} // end partitionIt()

快速排序算法本质上通过把一个数组划分为两个子数组,然后递归的调用自身为每一个子数组进行快速排序。

枢纽(Pivot)的选择:

选择数组最右端的数据项作为枢纽:

public void recQuickSort(int left, int right)

{

if(right-left <= 0) // if size <= 1,

return; // already sorted

else // size is 2 or larger

{

long pivot = theArray[right]; // rightmost item

// partition range

int partition = partitionIt(left, right, pivot);

recQuickSort(left, partition-1); // sort left side

recQuickSort(partition+1, right); // sort right side

}

} // end recQuickSort()

//--------------------------------------------------------------

public int partitionIt(int left, int right, long pivot)

{

int leftPtr = left-1; // left (after ++)

int rightPtr = right; // right-1 (after --)

while(true)

{ // find bigger item

while( theArray[++leftPtr] < pivot )

; // (nop)

// find smaller item

while(rightPtr > 0 && theArray[--rightPtr] > pivot)

; // (nop)

if(leftPtr >= rightPtr) // if pointers cross,

break; // partition done

else // not crossed, so

swap(leftPtr, rightPtr); // swap elements

} // end while(true)

swap(leftPtr, right); // restore pivot

return leftPtr; // return pivot location

} // end partitionIt()

当数据是有序的或者是逆序时,从数组的一端或者另外一端选择数据项作为枢纽都不是好办法,比如逆序时,枢纽是最小的数据项,每一次划分都产生一个有N-1个数据项的子数组以及另外一个只包含枢纽的子数组

三数据项取中划分:

选择第一个、最后一个以及中间位置数据项的中值作为枢纽

public void recQuickSort(int left, int right)

{

int size = right-left+1;

if(size <= 3) // manual sort if small

manualSort(left, right);

else // quicksort if large

{

long median = medianOf3(left, right);

int partition = partitionIt(left, right, median);

recQuickSort(left, partition-1);

recQuickSort(partition+1, right);

}

} // end recQuickSort()

//--------------------------------------------------------------

public long medianOf3(int left, int right)

{

int center = (left+right)/2;

// order left & center if( theArray[left] > theArray[center] )

swap(left, center);

// order left & right if( theArray[left] > theArray[right] )

swap(left, right);

// order center & right if( theArray[center] > theArray[right] )

swap(center, right);

swap(center, right-1); // put pivot on right return theArray[right-1]; // return median value } // end medianOf3()

public int partitionIt(int left, int right, long pivot)

{

int leftPtr = left; // right of first elem int rightPtr = right - 1; // left of pivot

while(true)

{

while( theArray[++leftPtr] < pivot ) // find bigger

; // (nop) while( theArray[--rightPtr] > pivot ) // find smaller

; // (nop) if(leftPtr >= rightPtr) // if pointers cross, break;

else

swap(leftPtr, rightPtr);

} // end while(true)

swap(leftPtr, right-1);

return leftPtr;

} // end partitionIt()

// partition done // not crossed, so // swap elements // restore pivot // return pivot location

更多相关推荐:
用php实现的各种排序算法总结

用php实现的各种排序算法总结优化php性能的五个实用技巧:以下是五个优化技巧,熟练掌握后对于开发还是很有帮助的。1.对字符串使用单引号PHP引擎允许使用单引号和双引号来封装字符串变量,但是这个是有很大的差别的…

各种排序算法的总结和比较

1快速排序(QuickSort)快速排序是一个就地排序,分而治之,大规模递归的算法。从本质上来说,它是归并排序的就地版本。快速排序可以由下面四步组成。(1)如果不多于1个数据,直接返回。(2)一般选择序列最左边…

Java各种排序算法总结

排序是程序开发中一种非常常见的操作对一组任意的数据元素或记录经过排序操作后就可以把他们变成一组按关键字排序的有序队列对一个排序算法来说一般从下面3个方面来衡量算法的优劣1时间复杂度它主要是分析关键字的比较次数和...

最常用的排序算法总结

实际应用中最常用的排序是快速排序和堆排序所谓堆排序就是将最小的一个值放到堆栈的顶部这样就可以使最后出来的数完成排序快速排序是不稳定的堆排序是稳定的所谓稳定就是当两个值相等时排序后两个值的顺序和排序前相同以上两种...

各种排序算法总结

1冒泡排序交换排序方法之一冒小泡voidBublesortintaintn定义两个参数数组首地址与数组大小intijtempfori0iltn1iforji1jltnj注意循环的上下限ifaigtajtempa...

各种算法排序思想小结

1.选择排序基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。2.直接插入排序基本思想:每次将一个待排序的记录,按其关键字大小插入到前…

各种排序算法小结

各种排序算法小结排序算法是一种基本并且常用的算法由于实际工作中处理的数量巨大所以排序算法对算法本身的速度要求很高而一般我们所谓的算法的性能主要是指算法的复杂度一般用O方法来表示在后面我将给出详细的说明对于排序的...

排序算法总结C语言

排序算法总结一插入排序InsertionSort1基本思想每次将一个待排序的数据元素插入到前面已经排好序的数列中的适当位置使数列依然有序直到待排序数据元素全部插入完为止2排序过程示例初始关键字493865977...

排序算法总结

插入排序代码给定待排序序列A1n现假设A1i已经有序那么我们取出Ai1插入到序列A1i这样有序序列记录数就增加了1如此重复上述操作不断取出记录插入有序序列直到An插入到有序序列排序完成publicclassma...

blog 常见排序算法总结

总结了5中常见算法冒泡排序选择排序插入排序快速排序和归并排序前三种比较简单只做简单介绍和代码举例后两种代码有些复杂做详细介绍冒泡排序定义两个for循环比较相邻元素前者比后者大就交换相邻元素选择排序定义初始最小项...

10种排序算法总结

10种排序算法总结20xx0920120117我来说两句收藏我要投稿排序算法有很多所以在特定情景中使用哪一种算法很重要为了选择合适的算法可以按照建议的顺序考虑以下标准1执行时间2存储空间3编程工作对于数据量较小...

排序算法汇总总结

排序算法汇总总结一插入排序直接插入排序InsertionSort的算法描述是一种简单直观的排序算法它的工作原理是通过构建有序序列对于未排序数据在已排序序列中从后向前扫描找到相应位置并插入插入排序在实现上通常采用...

各种排序算法总结(43篇)