一、查找
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]+" ");
}
}
}