标签:
插入排序法的思想是从前往后,先排序前两个元素,把第三个元素插入其中,然后让前三个已经排好序,再把第四个插入前三个中,排好序...以此类推,直到最后一个插入为止,这样便完成了插入排序。该算法的复杂度为n^2。
public class InsertSort { public static void main(String[] args) { //数组声明 int[] a = {5,1,3,0,1,4,-1}; int L = a.length; //首先确保前两个元素是升序的 if(a[1]<a[0]) { int tmp=a[0]; a[0]=a[1]; a[1]=tmp; } //其次进行插入排序 for(int i=2;i<L;i++) { //如果待插入的数小于或等于已排序的表头 if(a[i]<=a[0]) { int tmp=a[i]; for(int j=i;j>0;j--) { a[j]=a[j-1]; } a[0]=tmp; } //如果待插入的数大于或等于已排序的表尾 else if(a[i]>=a[i-1]) continue; //如果待插入的数介于已排序的表中某两个数中间 else { for(int k=0;k<i-1;k++) { if(a[i]>=a[k]&&a[i]<=a[k+1]) { int tmp1=a[i]; for(int m=i;m>k+1;m--) { a[m]=a[m-1]; } a[k+1]=tmp1; } } } } for(int element:a) System.out.println(element+" "); } }
堆排序的思想是,首先需要构造一个堆的数据结构,我们说程序=数据结构+设计模式,因此好的数据结构对程序具有至关重要的作用,堆是一种完全二叉树,父节点大于子节点,依据根节点是最大值这一重要特性,然后依次从根节点取出元素,使得堆依次重构,最后,即可完成排序。该算法复杂度为nlogn。
import java.util.*; /* * 本程序是进行堆排序 * 首先需要明白堆是一种特殊的完全二叉树,并且它的孩子结点永远小于父母结点 */ public class HeapSort<E extends Comparable> { public static void main(String[] args) { //声明一个列表,存储数据 Integer[]list={1,0,-2,3,5,1,2,10,11,21,3,2}; heapsort(list); for(Integer element:list) System.out.println(element); } /* * 首先编写堆类 * 堆类用线性列表来存储数据 * * */ private ArrayList<E> list=new ArrayList<E>(); public HeapSort(E[] objects) { for(int i=0;i<objects.length;i++) add(objects[i]); } public HeapSort() { } public void add(E object) { list.add(object); int currentindex=list.size()-1; while(currentindex>0) { int parentindex=(currentindex-1)/2; /* * 如果父类结点小于子类结点,则将它们交换值 * 这个过程一直持续到父类结点不再小于子类结点为止 */ if(list.get(parentindex).compareTo(list.get(currentindex))<0) { E temp=list.get(currentindex); list.set(currentindex, list.get(parentindex)); list.set(parentindex, temp); } else break; currentindex=parentindex;//把新加的数的下标更新 } } @SuppressWarnings("unchecked") public E remove() { if(list.size()==0) return null; /* * 基本思想是 * remove()方法只能移除根处的元素 * 然后重新组建堆 * 首先把最后一个元素移到根处 * 然后将根与它的结点进行比较,若小于其子结点,则交换下移即可 * 直到下标最大为止 */ E removedObject=list.get(0); list.set(0, list.get(list.size()-1)); list.remove(list.size()-1); int currentindex=0; while(currentindex<list.size()) { int leftchildindex=2*currentindex+1;//左孩子 int rightchildindex=2*currentindex+2;//右孩子 if(leftchildindex>=list.size()) break; /* * 下面语句确定左边子结点与右边子结点的大小 * 以便将父结点与最大的子结点进行比较 * 进而确定是否执行交换动作 */ int maxindex=leftchildindex; if(rightchildindex<list.size()) { if(list.get(maxindex).compareTo(list.get(rightchildindex))<0) maxindex=rightchildindex; } /* * 下面开始执行交换动作 * 若父结点比最大的子结点要小 * 则交换它们 */ if(list.get(currentindex).compareTo(list.get(maxindex))<0) { E temp=list.get(currentindex); list.set(currentindex, list.get(maxindex)); list.set(maxindex, temp); currentindex=maxindex; } /* * 直到父结点不再小于最大的子结点为止 */ else break; } return removedObject; } public static <E extends Comparable>void heapsort(E[]list) { HeapSort<E> heap=new HeapSort<E>(); for(int i=0;i<list.length;i++) heap.add(list[i]); for(int i=list.length-1;i>=0;i--) list[i]=heap.remove(); } }
归并排序的思想源自分而治之,即把一个大任务分割成两个小任务,再递归分割,直到不能分割为止。对于一个数组,我们可以将其分成两部分,再将各小部分分别分成两部分,最后使得数组分成N份,N为元素总数,再两两按大小合并,四四按大小合并...直到最后合并完整为止,即可完成排序。该算法复杂度为nlogn。
public class MergeSort { //归并排序,首选采用分而治之的思想,运用递归方法,将数组分组两半 public static void guibing(int[] list) { int L=list.length; //将数组递归分成两部分 if(L>1) { //第一部分为前一半元素 int[] firstHalf=new int[L/2]; //调用arrayCopy方法,将list中的前一半元素复制到firstHalf之中 System.arraycopy(list, 0, firstHalf, 0, L/2); //递归:将这个子数组再分成两半 guibing(firstHalf); //第二部分为后一半元素(不一定与第一部分元素个数相同) int[] secondHalf=new int[L-L/2]; //调用arrayCopy方法,将list中的后一半元素复制到secondHalf之中 System.arraycopy(list, L/2, secondHalf, 0, secondHalf.length); //递归:将这个子数组再分成两半 guibing(secondHalf); //一旦所有的递归拆分都已经结束,那么进行归并 int[]temp=merge(firstHalf,secondHalf); //将temp数组的所有元素复制到list之中 //参数的含义:源数组,首索引,目标数组,首索引,复制长度 System.arraycopy(temp, 0, list, 0, temp.length); } } //归并两个数组 //因为两个数组已经是排序的,所以只需依次比较两个元素的对应值即可,"谁小就谁上" private static int[] merge(int[] list1,int[] list2) { //声明最终数组及长度 int[] tmp=new int[list1.length+list2.length]; //设置索引量初始化 int current1=0,current2=0,current3=0; //当两个子数组均没有结束,需要比较它们的值 while(current1<list1.length&¤t2<list2.length) { if(list1[current1]<list2[current2]) tmp[current3++]=list1[current1++]; else tmp[current3++]=list2[current2++]; } //如果只剩下第一个子数组了,就直接把剩下的元素依次放入最终数组之中 while(current1<list1.length) tmp[current3++]=list1[current1++]; //如果只剩下第二个子数组了,就直接把剩下的元素依次放入最终数组之中 while(current2<list2.length) tmp[current3++]=list2[current2++]; //至此,合并结束,返回最终数组 return tmp; } public static void main(String[] args) { //首先声明数组 int[]a={-5,1,3,2,1,0,2,-2,0}; int L=a.length; //归并排序 guibing(a); //输出结果 for(int element:a) System.out.println(element); } }
快速排序算法的思想其实也是来自分治法,不过除了这个之外,还是用了定与不定的思想,即我在分割任务的同时,每一步都可以寻找一个定的元素,即找主元的位置。主元的位置一旦确定,即不会改变,而将N个元素两两分割直到不能分割为止,运用递归的思想,在每一小块中都寻找主元的位置。最终完成了快速排序。该算法复杂度为nlogn。
/* * @快速排序法 */ public class QuickSort { //快速排序主程序 public static void sort(int[] arr) { quickSort(arr,0,arr.length-1); } //快速排序法递归,表明要排序的数组,以及起始索引 private static void quickSort(int[]arr,int first,int last) { //只要最后一个大于第一个的索引 if(last>first) { //将数组分为两部分,并且选择第一个为主元 int pivotIndex=partition(arr,first,last); //对主元分开的两个子数组进行排序 quickSort(arr,first,pivotIndex-1); quickSort(arr,pivotIndex+1,last); } } //寻找主元并且划分数组的部分 public static int partition(int[] list,int first,int last)//划分数组为两部分 { //选择第一个为主元 int pivot=list[first]; //后面将数组划分为大于主元和小于主元的两大块 int low=first+1; int high=last; //如果high大于low while(high>low) { //如果low的元素小于pivot就继续推进 while(low<=high&&list[low]<=pivot) low++; //如果high的元素大于pivot就继续后退 while(low<=high&&list[high]>pivot) high--; //否则,说明出现了相反情况,则交换两个元素 if(high>low)//当list[high]<list[low]时,就交换二者 { int temp=list[high]; list[high]=list[low]; list[low]=temp; } } while(high>first&&list[high]>=pivot) high--; //如果一开始选的主元比最后一个high元素要大 if(pivot>list[high]) { list[first]=list[high]; list[high]=pivot; return high; } else return first; } public static void main(String[] args) { //声明数组 int[]arr={1,2,3,0,1,5,-1,2}; //调用快速排序算法 sort(arr); //输出结果 for(int element:arr) System.out.println(element); } }
冒泡排序估计是最为熟悉的,也是最好写的,它的思想是每一次遍历都会两两比较,比如说从最后一个元素往前遍历的话,遇到比自己大的就交换过来,于是,这样最后的话,相当于小的元素都浮上来了,形象地称为冒泡法,一共最多需遍历n趟,当然如果某一次遍历发现什么动作也没有,说明排序已经完成了。该算法复杂度为n^2。
public class BubbleSort { public static void main(String[] args) { //声明数组 int[]a={-5,1,3,2,1,0,2,-2}; int L=a.length; //声明临时变量 int tmp; int Flag=0; //若某次遍历中Flag的值保持为1,则说明排序已经完成,可以退出了 while(Flag==0) { Flag=1; for(int i=0;i<L-1;i++) { //交换相邻元素 if(a[i]>a[i+1]) { tmp=a[i]; a[i]=a[i+1]; a[i+1]=tmp; Flag=0; } } } //输出结果 for(int element:a) System.out.println(element); } }
选择排序算法的思想也很简单,先假设第一个数为最小数,作为基准,然后依次向后轮询,遇到比最小的数还要小,就替换掉,一趟过后,第一个数就确定了,接下来以此类推,将第二个数确定下来......该算法复杂度为n^2.
public class SelectSort { public static void main(String[] args) { //首先声明数组 int a[]={-5,1,3,2,1,0,2,-2}; int L=a.length; //找到最小的数,依次放到表头... for(int i=0;i<L;i++) { //找出最小的数 for(int j=i+1;j<L;j++) { if(a[j]<a[i]) { int T=a[j]; a[j]=a[i]; a[i]=T; } } } //输出结果 for(int element:a) System.out.println(element); } }
标签:
原文地址:http://my.oschina.net/zzw922cn/blog/492095