您的位置:首页 > 理论基础 > 数据结构算法

数据结构 31 查找 搜索二叉树 哈希查找 中位数

2014-01-03 21:12 387 查看
1.搜索二叉树
小的左边 大的右边

typedef struct _NODE

{

int data;

struct _NODE* left;

struct _NODE* right;

}NODE;

const NODE* find_data(const NODE* pNode, int data){

if(NULL == pNode)

return NULL;

if(data == pNode->data)

return pNode;

else if(data < pNode->data)

return find_data(pNode->left, data);

else

return find_data(pNode->right, data);

}

2.hash查找
哈希表的定义如下:1)每个数据按照某种聚类运算归到某一大类,然后所有数据链成一个链表;
2)所有链表的头指针形成一个指针数组。这种方法因为不需要完整排序,所以在处理中等规模数据的时候很有效。
其中节点的定义如下:

[cpp] view plaincopy

typedef struct _LINK_NODE

{

int data;

struct _LINK_NODE* next;

}LINK_NODE;

那么hash表下面的数据怎么查找呢?

[cpp] view plaincopy

LINK_NODE* hash_find(LINK_NODE* array[], int mod, int data) // 这里我更喜欢用一个队列数组 当然数组指针也是可以的

{

int index = data % mod;

if(NULL == array[index])

return NULL;

LINK_NODE* pLinkNode = array[index];

while(pLinkNode)

{

if(data == pLinkNode->data)

return pLinkNode;

pLinkNode = pLinkNode->next;

}

return pLinkNode;

}

分析:
hash表因为不需要排序,只进行简单的归类,在数据查找的时候特别方便。查找时间的大小取决于mod的大小。mod越小,那么hash查找就越接近于普通查找;那么hash越大呢,那么hash一次查找成功的概率就大大增加。

3.中位数 随机选择
思路:
1.在数组中随机找个元素,将比它大的放在它后面比它小的放在它前面,进行排列
2.返回排列后它的位置, 将此时的位置与要找的位置即(中位),作对比,
如果相等 找到
如果小于 在高位中继续递归查找
如果大于 在低位中继续递归查找

#include<iostream>
using namespace std;

//将第1个元素移动到指定位置,且保证小于此元素的在其左边,大于的在其右边
static int get_middle(int *pArray,int start,int end)
{
if(start >= end)
return start;
int midvalue = pArray[start];
int save_ptr = start;
int curr = start;

while(curr <= end)
{
if(pArray[curr] < midvalue)             // 如果当前值小于midvalue 将其移动到midvalue前
{
pArray[save_ptr] = pArray[curr];
pArray[curr] = pArray[save_ptr+1];  // 将save_ptr+1即它下一个位置的值保持到curr中
save_ptr++;                         // 指针右移
}
curr++;
}
pArray[save_ptr] = midvalue;                // 把坑填上
return save_ptr;
}

int get_random(int start, int end)
{
return (rand() % (end-start+1) + start);
}
void swap(int* xx, int* yy)
{
int *temp;
temp = xx;
xx = yy;
yy = temp;
}

int get_middle_random(int *pArray,int start,int end)
{
int mid = get_random(start,end);
swap(pArray+start,pArray+mid);                  // 1. 随机化方法,查找随机位置,与第1位交换。

return get_middle(pArray,start,end);            // 2. 以某个数为界将数组排列 并且返回它的位置
}

int _quick_search(int *pArray,int start,int end,int pos)
{
if(start >= end)
return pArray[end];

int mid = get_middle_random(pArray,start,end);

if(mid == pos)                                  // 找到
return pArray[mid];
else if(pos < mid)                              // pos在低位
return _quick_search(pArray,start,mid-1,pos);
else                                            // pos在高位
return _quick_search(pArray,mid+1,end,pos);
}

int QuickSearch(int *pArray,int cnt,int pos)
{
if(cnt <= 0)                                    // 判断参数的合法性
{
return 0;
}
if(pos > cnt)
pos = cnt;

return _quick_search(pArray,0,cnt-1,pos-1);     // 数组从0开始
}

int main()
{
int a[] = {1, 2, 5, 0, 8, 3, 9};
int size = sizeof(a) / sizeof(a[0]);
int mid;
if(size % 2 != 0)
{
mid = size / 2 + 1;
}
else
mid = size /2;

cout<<QuickSearch(a, size, mid)<<endl;

return 0;
}


2.求两个等长升序序列的中位数

1. 算法要求

一个长度为L(L≥1)的升序序列S,处在第L / 2(若为小数则去掉小数后加1)个位置的数称为S 的中位数。例如,若序列S1=(11,13,15,17,19),则S1 的中位数是15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若S2=(2,4,6,8,20),则S1 和S2 的中位数是11。现在有两个等长升序序列A 和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A 和B 的中位数。

2. 算法思想

分别求出序列A 和B 的中位数,设为a 和b,求序列A 和B 的中位数过程如下:

1)若a=b,则a 或b 即为所求中位数,算法结束。

2)若a<b,则舍弃序列A 中较小的一半,同时舍弃序列B 中较大的一半,要求舍弃的长度相等;

3)若a>b,则舍弃序列A 中较大的一半,同时舍弃序列B 中较小的一半,要求舍弃的长度相等;

在保留的两个升序序列中,重复过程1)、2)、3),直到两个序列中只含一个元素时为止,较小者即为所求的中位数。

3. 算法实现

int get_middle_number(int a[], int b[], int n)
{
int         start1 = 0, end1 = n-1, m1;
int         start2 = 0, end2 = n-1, m2;

while (start1 != end1 || start2 != end2)
{
m1 = (start1 + end1) / 2;
m2 = (start2 + end2) / 2;
if (a[m1] == b[m2])      // (1)
return a[m1];
if (a[m1] < b[m2]) {     // (2)
if ((start1+end1) % 2 == 0) {
start1 = m1;
end2 = m2;
} else {
start1 = m1 + 1;
end2 = m2;
}
} else {                 // (3)
if ((start1+end1) % 2 == 0) {
end1 = m1;
start2 = m2;
} else {
end1 = m1;
start2 = m2 + 1;
}
}
}
return a[start1] < b[start2] ? a[start1] : b[start2];  // (4)
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: