java基础篇(3)——java中几种常用排序算法、查找算法、链表倒序

快速排序

1,基本思想:

随机找出一个数(通常就拿数组第一个数据就行),把它插入一个位置,使得它左边的数都比它小,它右边的数据都比它大,这样就将一个数组分成了两个子数组,然后再按照同样的方法把子数组再分成更小的子数组,直到不能分解为止。    它也是分治思想的一个经典实验(归并排序也是)。

2,算法

  1. public class QuickSort{  
  2.     public static void quickSort(Comparable[] a){  
  3.         //StdRandom.shuffle(a);//将数组a顺序打乱,消除对输入的依赖,这是《算法第四版》作者写好的静态函数,  
  4.         quickSort(a, 0, a.length-1);  
  5.     }  
  6.     public static void quickSort(Comparable[] a, int lo, int hi){  
  7.         if(hi <= lo)    //跳出递归的条件,相当于不能再分解了  
  8.             return;  
  9.         int j = partition(a, lo, hi);    //切分(将a[lo]插入到数组中合适的位置:左边比他小,右边比它大,这样就将数组切分成两部分)  
  10.         quickSort(a, lo, j-1);           //将左半部分a[lo...j-1]排序  
  11.         quickSort(a, j+1, hi);           //将右半部分a[j+1...hi]排序  
  12.     }  
  13.     private static int partition(Comparable[] a, int lo, int hi){  
  14.     //将数组切分为a[lo...i-1]、a[i] 和a[i+1...hi];  
  15.         int i = lo, j = hi + 1;   //左右扫描的指针,j=hi+1,很大的程度上是为了下面写--j,  
  16.         Comparable v = a[lo];     //把要用来切分的元素保留  
  17.         while(true){              // 扫描左右检查扫描是否结束并交换元素  
  18.             while(less(a[++i], v))//两种条件会跳出while循环,直到在左侧找到比v大的,或i指针已经走到头了(i==hi),++i的原因:v是从lo开始的,满足less()  
  19.                 if(i == hi)   break;//不过这两个判断越界的测试条件是多余的,可以去掉,因为本身i,j就是从两端走过去的,不等走到头就  
  20.             while(less(v,a[--j]));  
  21.                 if(j == lo)   break;  
  22.             if(i >= j)    break;  //i和j碰上了,那就跳出整个循环,  
  23.             exch(a,i,j);          //如果上两个while都跳出,说明i,j停在了a[i]>v ,a[j]<v处,所以将二者交换就可以了,然后i和j继续向中间靠拢  
  24.         }  
  25.         exch(a, lo, j);           //将  v = a[j]放入正确的位置,当两个指针相遇时,交换a[lo]和a[j],这样切分的值就留在a[j]中了,初始的a[lo]找到了正确位置  
  26.         return j;                 //a[lo...j-1] <= a[j] <= a[j+1...hi]达成  
  27.     }  
  28. }  
复杂度分析
排序方法 时间复杂度 空间复杂度 稳定性 复杂性
平均情况 最坏情况 最好情况
快速排序 O(nlog2n) O(n2) O(nlog2n) O(log2n) 不稳定 较复杂

冒泡排序

(1)基本思想

冒泡排序的基本思想就是:从无序序列头部开始,进行两两比较,根据大小交换位置,直到最后将最大(小)的数据元素交换到了无序队列的队尾,从而成为有序序列的一部分;下一次继续这个过程,直到所有数据元素都排好序。

算法的核心在于每次通过两两比较交换位置,选出剩余无序序列里最大(小)的数据元素放到队尾。


(2)运行过程

冒泡排序算法的运作如下:

1、比较相邻的元素。如果第一个比第二个大(小),就交换他们两个。

2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大(小)的数。

3、针对所有的元素重复以上的步骤,除了最后已经选出的元素(有序)。

4、持续每次对越来越少的元素(无序元素)重复上面的步骤,直到没有任何一对数字需要比较,则序列最终有序。

算法:

  1. public static void bubble_sort(int[] arr) {  
  2.         int i, j, temp, len = arr.length;  
  3.         for (i = 0; i < len - 1; i++)  
  4.             for (j = 0; j < len - 1 - i; j++)  
  5.                 if (arr[j] > arr[j + 1]) {  
  6.                     temp = arr[j];  
  7.                     arr[j] = arr[j + 1];  
  8.                     arr[j + 1] = temp;  
  9.                 }  
时间复杂度 O(n²)

二分查找

二分查找算法:是一种在有序数组中查找某一特定元素的搜索算法。

二分查找思想:搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组 为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。折半搜索每次把搜索区域减少一半,时间复杂度为Ο(logn)。、

二分查找算法要求:1>必须采用顺序存储结构;2>必须按关键字大小有序排列

算法实现

[cpp]  view plain  copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4. //二分查找: 递归实现  
  5. int binarySearch(int a[],int low,int high,int key)  
  6. {  
  7.     int mid=low+(high-low)/2;  
  8.   
  9.     if(low>high)  
  10.         return -1;  
  11.     else{  
  12.         if(a[mid]==key)  
  13.             return mid;  
  14.         else if(a[mid]>key)  
  15.             return binarySearch(a,low,mid-1,key);  
  16.         else  
  17.             return binarySearch(a,mid+1,high,key);  
  18.       
  19.     }  
  20.   
  21. }  
  22. //二分查找:非递归方法实现  
  23. int binarySearch(int a[],int n,int key)  
  24. {  
  25.     int low=0,high=n-1;  
  26.     int mid;  
  27.     while(low<=high)  
  28.     {  
  29.         mid=(low+high)/2;  
  30.         if(key==a[mid])  
  31.             return mid;  
  32.         else if(key<a[mid])  
  33.             high=mid-1;  
  34.         else  
  35.             low=mid+1;  
  36.     }  
  37.     return -1;  
  38. }  
  39. int main()  
  40. {  
  41.     int a[8]={1,3,4,5,6,7,9,10};  
  42.     int index=0;  
  43. //  index=binarySerach(a,0,8,3);  
  44.     index=binarySearch(a,8,3);  
  45.     cout<<"下表索引:"<<index<<endl<<"输出要查找的值:"<<a[index]<<endl;  
  46.     return 0;  
  47. }  
二分查找的优点:二分查找法的O(log n)让它成为十分高效的算法,是比较次数少,查找速度快,平均性能好
二分查找法的缺陷:数组必须有序

回文判断

给定一个字符串,如何判断这个字符串是否是回文串?

所谓回文串,是指正读和反读都一样的字符串,如madam、我爱我等。

解决上述问题,有两种方法可供参考:

(1)从字符串两头往中间扫;

(2)从字符串中间往两头扫。

具体代码如下:

复制代码
package com.liuzhen.string_1;

import java.util.Scanner;

public class StringPalindrome {
    //方法1:两头往中间扫
    public boolean IsPalindrome1(String A){
        char[] arrayA = A.toCharArray();
        int top = 0;
        int end = arrayA.length-1;
        if(A.equals("") || A.equals(null))    //非法输入
            return false;
        while(top < end){
            if(arrayA[top++] != arrayA[end--])
                return false;
        }
        return true;
    }
    
    //方法2:中间往两头扫
    public boolean IsPalindrome2(String A){
        char[] arrayA = A.toCharArray();
        int lenA = arrayA.length;
        int mid = lenA/2;
        int front;         //前半部分
        int back;          //后半部分
        if(lenA % 2 == 0){   //当字符串长度为偶数时
            front = mid-1;
            back = mid;
        }
        else{
            front = mid -1;
            back = mid + 1;
        }
        if(A.equals("") || A.equals(null))
            return false;
        while(front >= 0 && back < lenA){
            if(arrayA[front--] != arrayA[back++])
                return false;
        }
        return true;
    }
    
    public static void main(String[] args){
        StringPalindrome test = new StringPalindrome();
        Scanner in = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String A = in.nextLine();
        if(test.IsPalindrome1(A))
            System.out.println("使用方法1判断结果为,输入字符串是回文字符串");
        else
            System.out.println("使用方法1判断结果为,输入字符串不是回文字符串");
        if(test.IsPalindrome2(A))
            System.out.println("使用方法2判断结果为,输入字符串是回文字符串");
        else
            System.out.println("使用方法2判断结果为,输入字符串不是回文字符串");
    }
}

运行结果:

复制代码
请输入一个字符串:
我爱我
使用方法1判断结果为,输入字符串是回文字符串
使用方法2判断结果为,输入字符串是回文字符串


请输入一个字符串:
我爱你
使用方法1判断结果为,输入字符串不是回文字符串
使用方法2判断结果为,输入字符串不是回文字符串


请输入一个字符串:
abba
使用方法1判断结果为,输入字符串是回文字符串
使用方法2判断结果为,输入字符串是回文字符串

链表倒序

  1. /** 
  2.  * java 实现单链表的逆序 
  3.  * @author Administrator 
  4.  * 
  5.  */  
  6. public class SingleLinkedReverse {  
  7.       
  8.     class Node{  
  9.         int data;  
  10.         Node next;  
  11.           
  12.         public Node(int data){  
  13.             this.data = data;  
  14.         }   
  15.     }  
  16.    
  17.     public static void main(String[] args) {  
  18.         SingleLinkedReverse slr = new SingleLinkedReverse();  
  19.         Node head, tail;  
  20.         head = tail = slr.new Node(0);  
  21.         for(int i=1; i<10; i++){  
  22.             Node p = slr.new Node(i);  
  23.             tail.next = p;  
  24.             tail = p;  
  25.         }  
  26.         tail = head;  
  27.         while(tail != null){  
  28.             System.out.print(tail.data+"  ");  
  29.             tail = tail.next;  
  30.         }  
  31.           
  32.         head = reverse(head);  
  33.           
  34.         System.out.println(" ");  
  35.         while(head != null){  
  36.             System.out.print(head.data+"  ");  
  37.             head = head.next;  
  38.         }  
  39.     }  
  40.   
  41.     private static Node reverse(Node head) {  
  42.         Node p1,p2 = null;  
  43.         p1 = head;  
  44.           
  45.         while(head.next != null){  
  46.             p2 = head.next;  
  47.             head.next = p2.next;  
  48.             p2.next = p1;  
  49.             p1 = p2;  //重点代码
  50.         }  
  51.         return p2;  
  52.     }  
  53. }  

测试结果:

0  1  2  3  4  5  6  7  8  9   
9  8  7  6  5  4  3  2  1  0 


猜你喜欢

转载自blog.csdn.net/u012803478/article/details/80052231
今日推荐