数据结构4--查找和排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zl_best/article/details/53385337

一、查找

1.顺序查找

顺序查找是最基本的查找顺序,时间复杂度为O(n),查找过程为:从表中第一个元素开始按顺序逐个进行遍历,若查找到记录则返回,若直到最后一个没有查到,则查找失败。

2.二分查找

折半查找(Binary Search)技术,又称为二分查找,它的前提是线性表中的记录必须是关键码有序(通常从小到大有序),线性表必须采用顺序存储,其时间复杂度为O(logn)

基本思想在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功,或所有查找区域无记录,则查找失败。

3.查找树方法

(1)二叉查找树

二叉查找树又叫二叉排序树,需满足以下性质:

 1.若它的左子树非空,则左子树上所有记录的值均小于根记录的值;

 2.若它的右子树非空,则左子树上所有记录的值均小于根记录的值;

 3.左,右子树又各是一棵二叉查找树。

(2)平衡二叉树

定义:它的左子树和右子树的深度之差的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。

平衡因子(BF):结点的左子树的深度减去右子树的深度,那么显然-1<=bf<=1;

二、排序

1.插入类排序

基本思想:不断地将待排序的元素插入到有序序列中,使有序序列不断地扩大,直至所有元素都被插入到有序序列中。

(1)直接插入排序

基本操作:将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增1的有序表。

注:最好情况时间复杂度为O(n),最坏为O(n2).

(2)希尔排序

基本思想:将待排序的记录分成几组,从而减少参与直接插入排序的数据量,当经过几次分组之后,记录的排列已经基本有序,这时再对所有记录实施直接插入排序。

注:时间复杂度为O(n1.3).

2.交换类排序

基本思想:在排序过程中,通过对待排序记录序列中的元素进行比较,如果发现次序相反,就将存储位置交换来达到排序的目的。

(1)冒泡排序

基本思想:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。

注:平均时间复杂度为O(n2).

(2)快速排序

基本思想:通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

注:平均时间复杂度为O(nlog2n).
3.选择类排序

基本思想:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的记录序列的最后,直到全部排列完为止。

(1)简单选择排序

基本思想:第一趟从所有的n个记录中选择最小的记录放在第一位,第二趟从n-1个记录中选择最小的记录放在第二位,以此类推,经过n-1趟排序之后,整个待排序序列就成为有序序列了。

注:平均时间复杂度为O(n2).

(2)堆排序

堆:可以看成是一棵二叉树,其中每个非叶子节点的值均不大于(或不小于)其左、右孩子节点的值。

堆排序基本思想:首先将待排序的记录序列构造为一个堆,此时选择堆中所有记录的最小记录或最大记录,然后将它从堆中移出,并将剩余的记录再调整成堆,这样就又找到了次大(或次小)的记录。以此类推,直到堆中只有一个记录为止,每个记录出堆的顺序就是一个有序序列。

注:时间复杂度为O(nlog2n).

4.归并类排序

基本思想:将两个或两个以上有序的子序列合并成一个有序的序列。

(1)二路归并排序

基本思想:如果初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止

注:时间复杂度为O(nlog2n).

基本查找与排序的java代码实现如下:

import java.io.*;
import java.util.*;
/**
 * 排序与查找类
 * */
public class SearchingList {
    private int[] list;
    private StringTokenizer st;
    private int number;
    public SearchingList() throws IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        String line;
        System.out.print("请输入元素总个数:");
        this.number=Integer.parseInt(in.readLine());
        this.list=new int[number];
        System.out.println("请输入各元素,用空格隔开:");
        line=in.readLine();
        if(!line.isEmpty())
            st=new StringTokenizer(line);
        for(int i=0;i<this.number&&st.hasMoreTokens();i++){
            this.list[i]=Integer.parseInt(st.nextToken());
        }
        System.out.println("原序列:");
        this.output(list);
        System.out.println();
    }
    /**
     * 顺序查找
     * 时间复杂度为O(n)
     * @throws IOException
     * @throws NumberFormatException
     * */
    public void dirSearch() throws NumberFormatException, IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        System.out.println("顺序查找:请输入所要查找的元素:");
        int e = Integer.parseInt(in.readLine());
        int k=0;
        while(k<this.number&&this.list[k]!=e)
        	k++;
        if(k<this.number)
        	System.out.println("在位置"+k+"找到元素"+e);
        else 
        	System.out.println("没有找到元素"+e);
    }
    /**
     * 折半查找
     * 前提是线性表是有序的
     * 时间复杂度为O(logn)
     * @throws IOException
     * @throws NumberFormatException
     * */
    public void binSearch() throws NumberFormatException, IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        System.out.println("折半查找:请输入所要查找的元素:");
        int e = Integer.parseInt(in.readLine());
        int low = 1; 
        int high = this.number;
        int mid,temp,t=0;
        int[] list=this.copyList();
        //排序(简单选择)
        for(int i=0;i<this.number;i++){
            int j = i;
            for(int k = i+1;k<this.number;k++)
                if(list[k]<list[j])
                	j=k;
            if(j!=i){
                temp=list[j];
                list[j]=list[i];
                list[i]=temp;
            }
        }
        //查找
        while(low <= high){
               t++;
               mid=(low + high)/2;
               if(e==list[mid]){
                   System.out.println("在第"+t+"趟找到元素"+e);//找到
                   return;}
               else if(e<list[mid])
            	   high=mid-1;//左半区
               else 
            	   low=mid+1;//右半区
           }
           System.out.println("没有找到元素"+e);

    }
    /**
     * 直接插入排序
     * 最好情况时间复杂度为O(n),最坏为O(n2)
     * */
    public void dirInsertionSort(){
    	int[] list=this.copyList();
		int i,j,temp;
		for(i = 1;i<list.length;i++){
			temp = list[i];
              //这段表示前后两个元素 A与B,B的值放到temp中,当A值比temp大的时候,前面的元素即A,往后移动一个位置到B的位置
			for(j=i-1;j>=0 && list[j]>temp; j--){
				list[j+1] = list[j];  
			}
			list[j+1] = temp;   
		}
		this.output(list);
        System.out.println();
    }
    /**
     * 冒泡排序
     * 平均时间复杂度为O(n2)
     * */
    public void bubbleSort(){
        int temp,lastExchange,num = 1;
        int i=this.number;
        int[] list=this.copyList();
        System.out.println("冒泡排序:");
        while(i>1){
            lastExchange=1;
            for(int j=0;j<i;j++)
                if(list[j]>list[j+1]){
                    temp=list[j+1];
                    list[j+1]=list[j];
                    list[j]=temp;//交换元素
                    lastExchange=j;//记下进行交换的记录位置
                }
            i=lastExchange;
            //输出每一步的结果
            System.out.print("第"+num+"趟:");
            for(int k=0;k<this.number;k++)
                System.out.print(list[k]+" ");
            System.out.println();
            num++;
        }
    }
    /**
     * 简单选择排序
     * 平均时间复杂度为O(n2)
     * */
    public void simpleSelectSort(){
        int j,k,temp;
        int[] list=this.copyList();
        System.out.println("简单选择排序:");
        for(int i=0;i<this.number;i++){
            j=i;
            for(k=i+1;k<this.number;k++)
                if(list[k]<list[j])
                	j=k;
            if(j!=i){
                temp=list[j];
                list[j]=list[i];
                list[i]=temp;
            }
            System.out.print("第"+i+"趟:");
            this.output(list);
            System.out.println();
        }
    }
    /**序列的副本*/
    private int[] copyList(){
        int[] inlist=new int[this.number];
        for(int i=0;i<this.number;i++){
            inlist[i]=this.list[i];
        }
        return inlist;
    }
    /**输出序列*/
    private void output(int[] list){
        for(int i=0;i<this.number;i++){
            System.out.print(list[i]+" ");
        }
    }
} 




阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页