数据结构 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.返回排列后它的位置, 将此时的位置与要找的位置即(中位),作对比,
如果相等 找到
如果小于 在高位中继续递归查找
如果大于 在低位中继续递归查找
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. 算法实现
小的左边 大的右边
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) }
相关文章推荐
- 数据结构复习之二叉树:遍历、搜索节点&路径、查找、与单链表互转、逐层打印
- 数据结构---搜索二叉树的插入、删除、查找
- 数据结构二叉树的查找与遍历
- 数据结构之查找二叉树
- 数据结构::搜索二叉树
- 数据结构 找到二叉树中的最大搜索二叉子树
- 每周数据结构【5】:在二叉树中递归查找为data值的点
- 【数据结构】二叉树的查找及第K行子树个数计算
- 数据结构二叉树的遍历、查找、删除
- 数据结构(六)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 数据结构-哈希二叉树
- 知识布局-数据结构-搜索二叉树
- 数据结构-查找二叉树(Binary Sort Tree)
- 9-7-平衡二叉排序(搜索)树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构 c语言实现哈希(hash)表查找 除留余数法构建hash函数开放定值法线性探测处理冲突
- 搜索二叉树的基本操作(增加,删除,查找)递归与非递归算法
- 数据结构_查找二叉树中值为key的节点,并将指针指向该节点_C语言源代码
- 数据结构 35 查找 哈希红黑树
- C#来完成二叉树的搜索、遍历、及查找
- 数据结构二叉树的java实现,包括二叉树的创建、搜索、删除和遍历