Java面试问题急。谢谢你。

2.归并排序体现了分而治之的思想,即把一个要排序的数组分成两部分,对这两部分进行归并排序,然后将两个排序后的数组进行归并。这种思想可以通过递归很容易地实现。归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。

实现代码如下:

# include & ltstdio.h & gt

#包含“common.h”

void merge(int data[],int p,int q,int r)

{

int i,j,k,n1,N2;

n 1 = q-p+1;

N2 = r-q;

int L[n 1];

int R[N2];

for(i = 0,k = p;我& ltn 1;i++,k++)

l[I]= data[k];

for(i = 0,k = q+1;我& ltN2;i++,k++)

r[I]= data[k];

for(k = p,i = 0,j = 0;我& ltn1。& ampj & ltN2;k++)

{

if(L[I]& gt;R[j])

{

data[k]= L[I];

i++;

}

其他

{

data[k]= R[j];

j++;

}

}

如果(我& ltn1)

{

for(j = I;j & ltn 1;j++,k++)

data[k]= L[j];

}

if(j & lt;n2)

{

for(I = j;我& ltN2;i++,k++)

data[k]= R[I];

}

}

void merge_sort(int data[],int p,int r)

{

如果(p & ltr)

{

int q =(p+r)/2;

merge_sort(data,p,q);

merge_sort(data,q + 1,r);

merge(数据,p,q,r);

}

}

void test_merge_sort()

{

int data[] = {44,12,145,-123,-1,0,121 };

printf(" -合并排序-\ n ");

out_int_array(data,7);

merge_sort(data,0,6);

out_int_array(data,7);

}

int main()

{

test_merge_sort()。

返回0;

}

4.对于有n个节点(e0,e1,…,en-1)的线性表,重新排列线性表节点的过程称为排序。排序时引用的数据项称为排序代码,通常选择节点的键值作为排序代码。

如果线性表中排序码相等的节点按一定的排序方法排序,仍能保持排序前的相对顺序,称之为稳定;否则这种排序方式就被说成不稳定。

在排序过程中,线性表的所有节点都在内存中,它们在线性表中的存储顺序在内存中进行调整,这就是所谓的内部排序。在排序过程中,只是将线性表中的部分节点调入内存,借助内存调整节点在外存中存储顺序的排序方式就变成了外排序。

下表简要介绍了几种常见的内部排序方法,并比较了它们的性能特点。

分类方法

简介

平均太阳时

最坏情况

辅助存储

稳定吗?

简单排序法

选择排序法

从线性表未排序的部分重复选择键值最小的节点,按照从线性表中选择的顺序排列节点,再次组成线性表。直到未排序部分为空,重构的线性表才是有序线性表。

o()

o()

O(1)

易变的

直接插入排序

假设线性表的第一个I节点序列e0,e1,…,en-1排序。找到这个有序节点ei序列中节点的插入位置,插入ei,使i+1节点序列e0,e1,…,ei也变成有序。依次对i=1,2,…,n-1进行这样的插入步骤,最终实现线性表的排序。

o()

o()

O(1)

稳定的

冒泡排序

对于范围内所有目前没有排序的节点,从上到下依次比较调整相邻的两个节点,使键值大的节点下沉,键值小的节点上升。即每当两个相邻的进行比较,发现它们的排列顺序与排序要求相反时,就进行交换。

o()

o()

O(1)

稳定的

谢尔分类

直接插入排序的一种改进,也称为“缩减增量排序”。首先将待排序的整列分成若干子序列进行直接插入排序,当整个序列中的记录“基本有序”时,所有记录再次直接插入排序。

千牛

o()

o(登录)

易变的

快速排序

冒泡排序的本质改进。一看,要排序的序列长度可以大大减少。一瞥之后,让一个节点移到中间的右边位置,让它左边序列的节点的键值比它自己的小,而它右边序列的节点的键值不要比它自己的小。把这样的一瞥叫做“师”。每一次划分都将一个长序列变成两个新的更小的子序列,这两个更小的子序列被等分,直到新的子序列的长度为1。当所有子序列的长度为1时,该序列已经是有序的。

O(nlogn)

o()

o(登录)

易变的

堆排序

树选择排序是对直接选择排序的有效改进。堆是按顺序存储的二叉树,其所有父节点(e[i])的键值不小于其左子节点(e[2*i+1])和右子节点(e[2*i+2])的键值。最初,如果把要排序的序列的n个节点看作一棵按顺序存储的二叉树,调整它们的存储顺序使之成为堆,然后堆的根节点的键值最大。然后根节点与堆的最后一个节点交换,缺一个节点的n-1节点重新调整使其重新成为堆。这样,在根节点处获得了节点序列的键值的第二大值。以此类推,直到堆中只剩下两个节点,并交换它们,最后得到一个有序的n节点序列。

O(nlogn)

O(nlogn)

O(1)

易变的

合并分类

将两个或多个有序子表合并成一个新的有序表。对于两个有序子表合并成一个有序表的双向组合排序,开始时,将n个节点的待排序序列看作由n个长度为1的有序子表组成,依次合并得到若干个长度为2的有序子表,然后成对合并...直到获得长度为n的有序表,排序完成。

O(nlogn)

O(nlogn)

O(n)

稳定的

后面根据各种排序算法给出了C语言的实现,大家复习的时候可以参考一下。

u-选择性分类

void ss_sort(int e[],int n)

{ int i,j,k,t;

for(I = 0;我& ltn-1;i++) {

for(k=i,j = I+1;j & ltn;j++)

if(e[k]& gt;e[j])k = j;

如果(k!=i) {

t = e[I];e[I]= e[k];e[k]= t;

}

}

}

u直接插入排序

void si_sort(int e[],int n)

{ int i,j,t;

for(I = 0;我& ltn;i++) {

对于(t=e[i],j = I-1;j & gt= 0 & amp& ampt & lte[j];j -)

e[j+1]= e[j];

e[j+1]= t;

}

}

u冒泡排序

void sb_sort(int e[],int n)

{ int j,p,h,t;

for(h = n-1;h & gt0;h=p) {

for(p = j = 0;j & lth;j++)

if(e[j]& gt;e[j+1]) {

t = e[j];e[j]= e[j+1];e[j+1]= t;

p = j;

}

}

}

u型希尔排序

void shell(int e[],int n)

{ int j,k,h,y;

for(h = n/2;h & gt0;h=h/2)

for(j = h;j & ltn;j++) {

y = e[j];

for(k = j-h;k & gt0 & amp& ampy & lte[k];k-=h)

e[k+h]= e[k];

e[k+h]= y;

}

}

u堆排序

无效筛选(e,n,s)

int e[];

int n;

int s;

{ int t,k,j;

t = e[s];

k = s;j = 2 * k+1;

while(j & lt;n) {

if(j & lt;n-1 & amp;& ampe[j]& lt;e[j+1])

j++;

if(t & lt;e[j]) {

e[k]= e[j];

k = j;

j = 2 * k+1;

}else破;

}

e[k]= t;

}

void heapsorp (int e[],int n)

{ int i,k,t;

for(I = n/2-1;我& gt=0;我-)

sift(e,n,I);

for(k = n-1;k & gt=1;k - ) {

t = e[0];e[0]= e[k];e[k]= t;

sift(e,k,0);

}

}

u快速排序

void r_quick(int e[],int low,int high)

{ int i,j,t;

if(低& lt高){

I =低;j =高;t = e[低];

while(我& ltj) {

while(我& lt强生公司。& ampe[j]& gt;t)j-;

如果(我& ltj)e[i++]= e[j];

while(我& lt强生公司。& ampe[I]& lt;= t)i++;

如果(我& ltj)e[j-]= e[I];

}

e[I]= t;

r_quick(e,低,I-1);

r_quick(w,i+1,高);

}

}

另外,外部排序是对大文件的排序,要排序的记录存储在外部存储器中。在排序过程中,文件中只有一部分记录存储在内存中,整个排序过程需要在内外存储器之间进行多次交换。

* * *查找

搜索就是在存储于某种数据结构中的数据集中找出满足指定条件的节点。

根据搜索条件,有节点的键码、键码以外的数据项或其他数据项的组合。根据内存或外存中的搜索数据,可分为内存搜索和外存搜索。根据搜索的目的,如果搜索只是确定具有指定条件的节点的存在,则成为静态搜索;搜索就是确定一个节点的插入位置或者删除找到的节点,这种搜索叫做动态搜索。

下面简单介绍几种常见的搜索方法。

查找u顺序存储线性表

这是最常见的查找方式。节点集以线性表的形式组织,并按顺序存储。节点只包含键码,是整数。如果线性表是无序的,则采用顺序搜索,即从线性表的一端开始逐个搜索。如果线性表是有序的,可以使用顺序搜索、二分法搜索或插值搜索。

u块搜索

块搜索的过程分为两步。首先用二分法在索引表中查找索引项,确定查找哪个节点。然后,在相应的块中顺序搜索。

u-linked存储线性表的搜索

对链接存储器的线性表的搜索只能从链表的第一个节点开始顺序进行。同样,无序链表和有序链表也有不同的搜索方法。

正在搜索u哈希表

哈希表也称散列表,是一种非常实用的搜索技术。它的原理是在一个节点的存储位置和它的关键代码之间建立一个确定的关系,这样搜索代码就可以直接利用这个关系来确定节点的位置。其技术的关键在于解决两个问题。

I .找到一个好的哈希函数