}
for(intj=size;j>i;j--){//movebiggeronesup
arr[j]=arr[j-1];
}
arr[i]=element;
size++;
}
得到有序数组的类封装MyOrderedArray类,测试该类中的insert方法:
publicvoidtestMyOrderedArray()throwsException{
MyOrderedArraymyOrderedArray=newMyOrderedArray();
myOrderedArray.insert(999);
myOrderedArray.insert(555);
myOrderedArray.insert(777);
myOrderedArray.show();//[555,777,999]
}
4.查找算法
1)线性查找
在查找过程中,将要查找的数一个一个地与数组中的数据项比较,直到找到要找的数。
在2.1中自定义的类封装数组MyArray的queryByValue方法,使用的就是线性查找。
2)二分查找
二分查找(又称折半查找),即不断将有序数组进行对半分割,每次拿中间位置的数和要查找的数进行比较:
如果要查找的数<中间数,则表明要查的数在数组的前半段;如果要查的数>中间数,则表明该数在数组的后半段;如果要查的数=中间数,则返回中间数。
在有序数组的类封装类MyOrderedArray中添加binarySearch方法
//根据值二分查找索引(前提:
有序)
publicintbinarySearch(longvalue){
intmiddle=0;
intleft=0;
intright=size-1;
while(true){
middle=(left+right)/2;
if(arr[middle]==value){
returnmiddle;//foundit
}elseif(left>right){
return-1;//can'tfoundit
}else{//dividerange
if(arr[middle]>value){
right=middle-1;//inlowerhalf
}else{
left=middle+1;//inupperhalf
}
}
}
}
测试该二分查找方法:
publicvoidtestMyOrderedArray()throwsException{
MyOrderedArraymyOrderedArray=newMyOrderedArray();
myOrderedArray.insert(999);
myOrderedArray.insert(555);
myOrderedArray.insert(777);
myOrderedArray.insert(333);
System.out.println(myOrderedArray.binarySearch(333));//0
}
第二讲简单排序
本讲提到的排序算法都假定了数组作为数据存储结构,本讲所有算法的时间复杂度都是。
在大多数情况下,假设当数据量比较小或基本上有序时,插入排序算法是三种简单排序算法中最好的选择,是应用最多的。
对于更大数据量的排序来说,后面讲到的快速排序通常是最快的方法。
1.冒泡排序
1)基本思想
在要排序的一组数中,对当前还未排好序的范围内的全部数,自下而上对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。
即:
每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
2)算法实现
冒泡排序的Java代码:
//bubblesort
publicstaticvoidbubbleSort(long[]arr){
longtemp;
for(inti=0;ifor(intj=arr.length-1;j>i;j--){//innerloop(backward)
if(arr[j]temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
}
}
}
}
测试冒泡排序及输出结果:
publicvoidtestBubbleSort()throwsException{
long[]arr={79,91,13,52,34};
Sort.bubbleSort(arr);
System.out.println(Arrays.toString(arr));//[13,34,52,79,91]
}
2.选择排序
1)基本思想
在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。
与冒泡排序相比,选择排序将必要的交换次数从O(N*N)减少到O(N),但比较次数仍然保持为O(N*N)。
2)算法实现
选择排序的Java代码:
//selectsort
publicstaticvoidselectSort(long[]arr){
longtemp;
for(inti=0;iintk=i;//locationofminimum
for(intj=i+1;jif(arr[j]k=j;//anewminimumlocation
}
}
temp=arr[i];
arr[i]=arr[k];
arr[k]=temp;
}
}
测试选择排序及输出结果:
publicvoidtestSelectSort()throwsException{
long[]arr={79,91,13,52,34};
Sort.selectSort(arr);
System.out.println(Arrays.toString(arr));//[13,34,52,79,91]
}
3.插入排序
1)基本思想
在要排序的一组数中,假设前面(n-1)[n>=2]个数已经是排好顺序的(局部有序),现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。
如此反复循环,直到全部排好顺序。
在插入排序中,一组数据仅仅是局部有序的;而冒泡排序和选择排序,一组数据项在某个时刻是完全有序的。
2)算法实现
插入排序的Java代码:
//insertsort
publicstaticvoidinsertSort(long[]arr){
longtemp;
for(inti=1;itemp=arr[i];//removemarkeditem
intj=i;//startshiftsati
while(j>=1&&arr[j-1]>temp){//untiloneissmaller
arr[j]=arr[j-1];//shiftitemright
j--;//goleftoneposition
}
arr[j]=temp;//insertmarkeditem
}
}
测试插入排序以及输出结果:
publicvoidtestInsertSort()throwsException{
long[]arr={79,91,13,52,34,34};
Sort.insertSort(arr);
System.out.println(Arrays.toString(arr));
//[13,34,34,52,79,91]
}
第三讲栈和队列
栈和队列都是抽象数据类型(abstractdatatype,ADT),它们既可以用数组实现,又可以用链表实现。
1.栈
1)栈模型
栈(Stack,又LIFO:
后进先出)是一种只能在固定的一端进行插入和删除的数据结构。
栈只允许访问一个数据项:
即最后插入的数据项,移除这个数据项后才能访问倒数第二个插入的数据项,以此类推。
栈可以用数组来实现,也可以用链表来实现。
2)栈的数组实现
栈的Java代码:
publicclassMyStack{
privatelong[]arr;//底层使用数组实现
privateinttop;
publicMyStack(){
arr=newlong[10];
top=-1;
}
publicMyStack(intmaxSize){
arr=newlong[maxSize];
top=-1;
}
//putitemontopofstack
publicvoidpush(longvalue){
arr[++top]=value;
}
//takeitemfromtopofstack
publiclongpop(){
returnarr[top--];
}
//peekattopofstack
publiclongpeek(){
returnarr[top];
}
//tureifstackisempty
publicbooleanisEmpty(){
return(top==-1);
}
//tureifstackisfull
publicbooleanisFull(){
return(top==arr.length-1);
}
}
测试栈的特性:
publicvoidtestMyStack()throwsException{
MyStackmyStack=newMyStack(4);
myStack.push(12);
myStack.push(34);
myStack.push(56);
myStack.push(78);
System.out.println(myStack.isFull());//true
while(!
myStack.isEmpty()){
System.out.print(myStack.pop());//78,56,34,12
if(!
myStack.isEmpty()){
System.out.print(",");
}
}
System.out.println();
System.out.println(myStack.isFull());//false
}
2.队列
1)队列模型
队列(Queue,又FIFO:
先进先出)是一种插入时在一端进行而删除时在另一端进行的数据结构。
为解决顺序队列假溢出问题,而采用循环队列:
即让队头、队尾指针在达到尾端时,又绕回到开头。
2)队列的数组实现
队列的Java代码:
publicclassMyQueue{
privatelong[]arr;
privateintsize;
privateintfront;
privateintrear;
publicMyQueue(){
arr=newlong[10];
size=0;
front=0;
rear=-1;
}
publicMyQueue(intmaxSize){
arr=newlong[maxSize];
size=0;
front=0;
rear=-1;
}
//putitematrearofqueue
publicvoidinsert(longvalue){
if(isEmpty()){//throwexceptionifqueueisfull
thrownewArrayIndexOutOfBoundsException();
}
if(rear==arr.length-1){//dealwithwraparound(环绕式处理)
rear=-1;
}
arr[++rear]=value;//incrementrearandinsert
size++;//incrementsize
}
//takeitemfromfrontofqueue
publiclongremove(){
longvalue=arr[front++];//getvalueandincrementfront
if(front==arr.length){//dealwithwraparound
front=0;
}
size--;//onelessitem
returnvalue;
}
//peekatfrontofqueue
publiclongpeek(){
returnarr[front];
}
//trueifqueueisempty
publicbooleanisEmpty(){
return(size==0);
}
//trueifqueueisfull
publicbooleanisFull(){
return(size==arr.length);
}
}
测试队列的特性:
publicvoidtestMyQueue()throwsException{
MyQueuemyQueue=newMyQueue(4);
myQueue.insert(12);
myQueue.insert(34);
myQueue.insert(56);
myQueue.insert(78);
System.out.println(myQueue.isFull());//true
while(!
myQueue.isEmpty()){
System.out.print(myQueue.remove());//12,34,56,78
if(!
myQue