Common Sorting Algo:

Bubble Sort: Runime: O(n2) average and worst case. Memory: O(1).

 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;
}
}

Selection Sort: Runtime: O(n2) average and worst case. Memory: O(1).

 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;
}
}
}

Merge Sort: Runtime: O(nlogn) average and worst case. Memory: Depends.

 void mergeSort(int[] array, int low,int high){
if(low < high){
int middle = (low + high) / 2;
mergeSort(array, low, middle);
mergeSort(array, middle + 1, high);
merge(array, low, middle, high);
}
}
void merge(int[] array, int low, int middle, int high){
int[] helper = new int[array.length];
for(int i = low; i <= high; i ++)
helper[i] = array[i];
int helperLeft = low;
int helperRight = middle + 1;
int current = low;
while(helperLeft <= middle && helperRight <= high){
if(helper[helperLeft] <= helper[helperRight])
array[current ++] = helper[helperLeft ++];
else
array[current ++] = helper[helperRight ++];
}
int remaining = middle - helperLeft;
for(int i = 0; i <= remaining; i ++)
array[current + i] = helper[helperLeft + i];
}

Quick Sort: Runtime: O(nlogn) average, O(n2) worse case. Memory: O(nlogn).

In quick sort, we pick a random element and partition the array, such that all numbers that are less than the partitioning element come before all elements that are greater than it. The partitioning can be performed efficiently through a series of swaps.

 void quickSort(int[] arr, int left, int right){
int index = partition(arr, left, right);
if(left < index - 1) quickSort(arr, left, index - 1);
if(right < index - 1) quickSort(arr, index, right);
}
int partition(int[] arr, int left, int right){
int pivot = arr[(left + right) / 2];
while(left <= right){
while(arr[left] < pivot) left ++;
while(arr[right] > pivot) right --;
if(left <= right){
swap(arr, left, right);
left ++;
right --;
}
}
return left;
}
 //pro4 : quick sort
public int adjust_array(int[] input,int low,int high){
//set the pivot to be the first element of the array
int pivot = input[low];
int exchange = 0;
while(low < high){
//from the tail to header,find the item smaller than the pivot
while(input[high] >= pivot && high > low)
high --;
exchange = input[high];
input[high] = input[low];
input[low] = exchange;
//from the header to tail,find the item larger than the pivot
while(input[low] <= pivot && high > low)
low ++;
exchange = input[high];
input[high] = input[low];
input[low] = exchange;
}
//set the mid to be pivot
input[low] = pivot; return low;
} public void quick_sort(int[] input, int low, int high){
//set the low and high pointer
if(low < high){
int mid = adjust_array(input,low,high);
quick_sort(input, 0, mid - 1);
quick_sort(input, mid + 1, high);
}
} public void pro4(){
int[] input = {20,1,2,40,7,90,11};
int low = 0;
int high = input.length - 1;
quick_sort(input,low,high);
for(int i = 0; i < input.length; i ++){
System.out.println(input[i]);
}
}

Radix Sort: Runtime: O(kn).

It is a sorting algo for intergers that takes advantage of the fact that integers have a finite number of bits.

 Void RadixSort(Node L[],length,maxradix)
{
Int m,n,k,lsp;
k=1;m=1;
Int temp[10][length-1];
Empty(temp); //清空临时空间
While(k<maxradix) //遍历所有关键字
{
For(int i=0;i<length;i++) //分配过程
{
If(L[i]<m)
Temp[0][n]=L[i];
Else
Lsp=(L[i]/m)%10; //确定关键字
Temp[lsp][n]=L[i];
n++;
}
CollectElement(L,Temp); //收集
n=0;
m=m*10;
k++;
}
}

Bucket sort:

Bucket sort, or bin sort, is a sorting algorithm that works by partitioning an array into a number of buckets. Each bucket is then sorted individually, either using a different sorting algorithm, or by recursively applying the bucket sorting algorithm. It is a distribution sort, and is a cousin of radix sort in the most to least significant digit flavour. Bucket sort is a generalization of pigeonhole sort. Since bucket sort is not a comparison sort, the Ω(n log n) lower bound is inapplicable. The computational complexity estimates involve the number of buckets.

Bucket sort works as follows:

  1. Set up an array of initially empty "buckets."
  2. Scatter: Go over the original array, putting each object in its bucket.
  3. Sort each non-empty bucket.
  4. Gather: Visit the buckets in order and put all elements back into the original array.

Pseudocode

function bucketSort(array, n) is
buckets ← new array of n empty lists
for i = 0 to (length(array)-1) do
insert array[i] into buckets[msbits(array[i], k)]
for i = 0 to n - 1 do
nextSort(buckets[i])
return the concatenation of buckets[0], ...., buckets[n-1]

Here array is the array to be sorted and n is the number of buckets to use. The function msbits(x,k) returns the k most significant bits of x (floor(x/2^(size(x)-k))); different functions can be used to translate the range of elements in array to n buckets, such as translating the letters A–Z to 0–25 or returning the first character (0–255) for sorting strings. The function nextSort is a sorting function; using bucketSort itself as nextSort produces a relative of radix sort; in particular, the case n = 2 corresponds toquicksort (although potentially with poor pivot choices).

Heap Sort: Runtime:O(nlgn) average and worse case.

 //堆排序
template
void Sort::HeapSort(T* array, int size)
{
int lastP = size / ;
//从最后一个有孩子的结点开始建初始堆
for(int i = lastP - ; i >= ; i--)
{
HeapAjust(array, i, size);
}
int j = size;
//将堆顶元素和无序区间的最后一个元素交换,再调整堆
while(j > )
{
Swap(array, , j - );
j--;
HeapAjust(array, , j);
}
}
//调整堆
template
void Sort::HeapAjust(T *array, int toAjust, int size)
{
int pos = toAjust;
while((pos * + ) < size)
{
int lChild = pos * + ;
if(array[lChild] > array[pos])
{
pos = lChild;//左孩子大
}
int rChild = lChild + ;
if(rChild < size && array[rChild] > array[pos])
{
pos = rChild;//右孩子更大
}
if(pos != toAjust) //父结点比其中一个孩子小
{
Swap(array, toAjust, pos);
toAjust = pos;
}
else
{
break;
}
}
}

Insertion Sort: Runtime O(n2).

 //插入排序
template
void Sort::InsertSort(T* array, int size)
{
for(int i = ; i < size; i++)
{
for(int j = i; j > ; j--)
{
if(array[j] < array[j - ])
{
Swap(array, j, j-);
}
}
}
}

Shell Sort: Runtim: O(nlog2^n) ~ O(n^1.5).

 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;
}
}
}
}

总结:

1.O(n^2)性能分析

平均性能为O(n^2)的有:直接插入排序,选择排序,冒泡排序

在数据规模较小时(9W内),直接插入排序,选择排序差不多。当数据较大时,冒泡排序算法的时间代价最高。性能为O(n^2)的算法基本上是相邻元素进行比较,基本上都是稳定的。

2.O(nlogn)性能分析

平均性能为O(nlogn)的有:快速排序,归并排序,希尔排序,堆排序。其中,快排是最好的, 其次是归并和希尔,堆排序在数据量很大时效果明显。

这四种排序可看作为“先进算法”,其中,快排效率最高,但在待排序列基本有序的情况下,会变成冒泡排序,接近O(n^2).

希尔排序对增量的标准没有较为满意的答案,增量对性能会有影响。

归并排序效率非常不错,在数据规模较大的情况下,比希尔排序和堆排序要好。

多数先进的算法都是因为跳跃式的比较,降低了比较次数,但牺牲了排序的稳定性。

3. 插入排序,冒泡排序,二叉树排序,归并排序都是稳定的

选择排序,希尔排序,快速排序,堆排序是不稳定的。

四、排序算法选择

1.数据规模较小

(1)待排序列基本序的情况下,可以选择直接插入排序

(2)对稳定性不作要求宜用选择排序,对稳定性有要求宜用插入或冒泡

2.数据规模不是很大

(1)完全可以用内存空间,序列杂乱无序,对稳定性没有要求,快速排序,此时要付出log(N)的额外空间。

(2)序列本身可能有序,对稳定性有要求,空间允许下,宜用归并排序

3.海量级别的数据,必须按块放在外存上

(1)对稳定性有求,则可考虑归并排序。

(2)对稳定性没要求,宜用堆排序

4.序列初始基本有序(正序),宜用直接插入,冒泡,随机快排

外部排序

外部排序指的是大文件的排序,面试的时候,面试官喜欢问,给你一个非常非常大的文件(比如1T),一行一个数(或者一个单词),内存最多只有8G,硬盘足够大,CPU很高级……然后要你给这个文件里面的数据排序。你要怎么办?

这其实就要用到外部排序。就是说要借助外存储器进行多次的内/外存数据的交换,因为内存不足以加载所有的数据,所以只能一部分一部分地加载。

所以外部排序的思想就是:分两个独立的阶段。

首先,可按内存的大小,将外存上含n个记录的文件分成若干长度为 x 的子文件或段,依次读入内存,并利用有效的内部排序方法对它们进行排序,并将排序后得到的有序子文件 重新写入外存,通常称这些有序的子文件为归并段或顺串。然后,对这些归并段进行逐趟归并,使归并段逐渐由小到大,直至得到整个有序文件为止。

因此现在的问题就转化为如何归并两个大文件。这个读者朋友们想一下就明白了。就是把这两个文件按内存的大小,一部分一部分从小到大加载出来并,再写回外存。

Questions:

11.1 Given two sorted arrays, A and B, where A has a large enough buffer at the end to hold B.

Merge a and b, starting from the last element in each!

11.2 Write a method to sort an array of strings so that all the anagrams are next to each other.

Implement comparator for this problem:

 public class AnagramComparator implements Comparator<String>{
public String sortChars(String s){
char[] content = s.toCharArray();
Arrays.sort(content);
return new String(content);
}
public int compare(String s1, String s2){
return sortChars(s1).compareTo(sortChars(s2));
}
}
 public void sort(String[] array){
Hashtable<String, LinkedList<String>> hash = new Hashtable<String, LinkedList<String>>();
for(String s : array){
String key = sortChars(s);
if(!hash.containsKey(key)) hash.put(key, new LinkedList<String>());
LinkedList<String> anagrams = hash.get(key);
anagrams.push(s);
}
int index = 0;
for(String key : hash.keySet()){
LinkedList<String> list = hash.get(key);
for(String t : list){
array[index] = t;
index ++;
}
}
}

The algorithm above is a modification of bucket sort.

11.3 Given a sorted array of n integers that has been rotated an unknown number of times, write code to find an element in the array. the array is sorted in increasing order at begining.

If we look a bit deeper, we can see that one half of the array must be ordered normally(in increasing order).We can therefore look at the normally ordered half to determine whether we should search the left or right half.

 public int search(int[] array, int left, int right, int x){
int mid = (left + right) / 2;
if(x == array[mid]) return mid;
if(left < right) return -1;
//either the left or right half must be normally ordered. find out which side is normally ordered, and then use the normally ordered half to figure out which side to search to find x.
if(array[left] < array[mid]){//left half normally ordered
if(x >= array[left] && x <= array[mid]) return search(array, left, mid - 1, x);
else return search(array, mid + 1, right, x);
}else if(array[mid] < array[left]){//right is normally ordered
if(x >= array[mid] && x <= array[right]) return search(array, mid + 1, right, x);
else return search(array, left, mid - 1, x);
}else if(array[left] == array[mid]){// left half is all repeats
if(array[mid] != array[right]) return search(array, mid + 1, right, x);
else{// else we have to search both halves
int result = search(array, left, mid - 1, x);
if(result == -1) return search(array, mid + 1, right, x);
else return result;
}
}
return -1;
}

11.4 Imagine you hace a 20GB file with one string per line. Explain how you would sort the file.

When an interviewer gives a size limit, it should tell you that they don't want you to bring all the data into memory.

So we should only bring part of the data into memory.

We'll divide the file into chunks which are xMB each, where x is the amout of memory we have available. Each chunk is sorted separately and then saved back to the file system.

Once all the chunks are sorted, we then merge the chunks, one by one. At the end, we have a fully sorted file.

 11.8 Imagine you are reading in a stream of integers. Periodically, you wish to be able to look up the rank of a number x(the number of values less than or equal to x). Implement the data structures and algorithms to support these operations.

 public class Question{
private static RankNode root = null;
public static void track(int number){
if(root == null) root = new RankNode(number);
else root.insert(number);
}
public static int getRankOfNumber(int number){
return root.getRank(number);
}
...
}
public class RankNode{
public int left_size = 0;
public RankNode left, right;
public int data = 0;
public RankNode(int d){
data = d;
}
public void insert(int d){
if(d <= data){
if(left != null) left.insert(d);
else left = new RankNode(d);
left_size ++;
}else{
if(right != null) right.insert(d);
else right = new RankNode(d);
}
}
public int getRank(int d){
if(d == data) return left_size;
else if(d < data){
if(left == null) return -1;
else return left.getRank(d);
}else{
int right_rank = right == null ? -1 : right.getRank(d);
if(right_rank == -1) return -1;
else return left_size + 1 + right_rank;
}
}
}

Chp11: Sorting and Searching的更多相关文章

  1. Algorithm in Practice - Sorting and Searching

    Algorithm in Practice Author: Zhong-Liang Xiang Date: Aug. 1st, 2017 不完整, 部分排序和查询算法, 需添加. Prerequisi ...

  2. 20162314 Experiment 3 - Sorting and Searching

    Experiment report of Besti course:<Program Design & Data Structures> Class: 1623 Student N ...

  3. CareerCup Chapter 9 Sorting and Searching

    9.1 You are given two sorted arrays, A and B, and A has a large enough buffer at the end to hold B. ...

  4. [Java in NetBeans] Lesson 15. Sorting and Searching.

    这个课程的参考视频和图片来自youtube. 主要学到的知识点有: Build in functions in java.util.Collections Need to implement a co ...

  5. [转]Paging, Searching and Sorting in ASP.Net MVC 5

    本文转自:http://www.c-sharpcorner.com/UploadFile/4b0136/perform-paging-searching-sorting-in-Asp-Net-mvc- ...

  6. OpenGL的学习资源

    OpenGL是3D图形接口工业标准,使用上非常简单,所有API不过上百个函数,但理解OpenGL就没那么简单,本文总结OpenGL的学习资源,包括官方资料.网上教程.示例程序等. Wikipedia: ...

  7. 用python语言讲解数据结构与算法

    写在前面的话:关于数据结构与算法讲解的书籍很多,但是用python语言去实现的不是很多,最近有幸看到一本这样的书籍,由Brad Miller and David Ranum编写的<Problem ...

  8. CareerCup All in One 题目汇总 (未完待续...)

    Chapter 1. Arrays and Strings 1.1 Unique Characters of a String 1.2 Reverse String 1.3 Permutation S ...

  9. [0x00 用Python讲解数据结构与算法] 概览

    自从工作后就没什么时间更新博客了,最近抽空学了点Python,觉得Python真的是很强大呀.想来在大学中没有学好数据结构和算法,自己的意志力一直不够坚定,这次想好好看一本书,认真把基本的数据结构和算 ...

随机推荐

  1. SQL2008、SQL2013 执行Transact-SQL 语句或者批处理时发生了异常。错误5120

    附加数据库的时候遇到问题,问题描述如下: 附加数据库 对于 服务器"服务器名"失败.(Microsoft.SqlServer.Smo) 执行Transact-SQL 语句或者批处理 ...

  2. 抽象类(abstract)是否可以继承自实体类 ?

    可以. 但是这个实体类必须有无参构造函数(默认的构造函数). 如: public class A { //这个构造函数必须要有(在没有构造函数重载时可以省略,因为运行时会为A添加默认构造函数) pub ...

  3. NDK 通过java调用so文件

    首先我们来看so文件的来源 1. 自己写.c文件,然后生成so库 2. 引用别人的静态库,或者动态库来生成新的jni调用库. 我们先来看最简单的编写一个jni调用的so库,包含一个获取字符串的方法,通 ...

  4. 为一个有数据没有主键id的数据表添加主键字段

    ALTER TABLE `photo_feedbacks` ADD COLUMN `id`  int(11) NOT NULL AUTO_INCREMENT FIRST ,ADD PRIMARY KE ...

  5. 【转载】Powershell获取世纪互联Office365中所有用户的OWA时区

    get-mailbox -resultsize unlimited | Get-MailboxRegionalConfiguration | select Identity,TimeZone | wh ...

  6. 拥抱ARM妹纸第二季 之 第一次 点亮太阳

    上次做鱼缸LED灯时还有很多材料正好拿来用.穆等等哥- 俺去找材料. 材料列表     3W LED   x  3     散热片     x  1     恒流IC     x  1     其他零 ...

  7. 插值和空间分析(一)_探索性数据分析(R语言)

    > library(lattice) > library(sp) > data(meuse) > coordinates(meuse) <- c("x" ...

  8. backbone前端基础框架搭建

    前端站点名为:site: 前端框架分为:css.js和img,框架的核心在js文件夹下: js中包括collections.models.views.lib和一个app入口js

  9. python之参数

    1. 参数传递有2种方式: 按位置传递, 按关键字传递. 2. 形参可以定义默认值, 可以用*收集元组, 可以用**收集字典. 其中, (1)指定默认值的形参可不接收实参. (2)指定*的形参用元组收 ...

  10. plateform_driver_register和plateform_device_register区别

    设备与驱动的两种绑定方式:在设备注册时进行绑定及在驱动注册时进行绑定. 以一个USB设备为例,有两种情形: (1)先插上USB设备并挂到总线中,然后在安装USB驱动程序过程中从总线上遍历各个设备,看驱 ...