查找相关

一、 实验目的
掌握顺序表的查找;
掌握哈希存储结构的思想,能选择合适的哈希函数,实现不同冲突处理方法的哈希表的查找、建立。

二、 实验内容及要求
(1) 顺序表的顺序查找
(2) 有序顺序表的二分查找的递归算法与非递归算法
(3) 哈希表查找
a) 设计哈希函数及处理冲突的方法;
b) 键盘输入数据,利用设计的哈希函数及线性探测法生成哈希表;
c) 用同样的输入数据和哈希函数,用链地址法处理冲突生成哈希表;
d) 在主函数中设计一个简单的菜单,分别调试上述算法;
(4)
(5)分析两种方法的平均查找长度。

ShunXuAndHash.h

#ifndef DACM_ZSN_SHUNXUBIAOCHAZHAO_H
#define DACM_ZSN_SHUNXUBIAOCHAZHAO_H
#define MaxSize 100  //表中元素的最大个数
typedef int ElemType;  //元素类型
typedef int KeyType;
typedef struct {
    ElemType *elem;  //线性表
    int length;   //表的实际长度
    int listsize;   //当前分配的存储容量
} SqList;   //顺序表的类型名


int InitList(SqList &L, int n);/*初始化顺序表*/
void CreateList(SqList &L);/*建立顺序表*/
void PrintList_Sq(SqList L);/*输出顺序表*/


typedef int KeyType;
typedef int IndoType;
typedef struct{
    int *elem;//数据元素存储地址,动态分配数组
    int count; //当前数据元素个数
}HashTable;

#define NULLKEY1 -1
void LianDiZhi();
void XianXingTanCe();
int SearchHash(HashTable *HT,int data,int HASHSIZE);
void SearchTest(int HASHSIZE);
int Hash(int data,int HASHSIZE);
void Init(HashTable *hashTable,int HASHSIZE);


#endif //DACM_ZSN_SHUNXUBIAOCHAZHAO_H

ShunXuAndHash.cpp

#include "ShuXuAndHash.h"
#include<bits/stdc++.h>
#include<stdlib.h>

using namespace std;


//初始化顺序表
int InitList(SqList &L, int n) {
    L.elem = (ElemType *) malloc(n * sizeof(ElemType));
    if (!L.elem) return 0;
    L.length = 0;
    L.listsize = n;
    return 1;
}


/*建立顺序表*/
void CreateList(SqList &L) {
    int i;
    printf("输入表的长度:");
    scanf("%d", &L.length);//输入表长
    printf("请输入%d个数", L.length);
    for (i = 1; i <= L.length; i++)
        scanf("%d", &L.elem[i - 1]);//输入元素
}

int ListInsert(SqList &L, ElemType e)    // 插入数据
{
    //先判断是否已满
    int i, j;
    if (L.length == L.listsize) {
        return -1;
    } else {
        i = L.length - 1;
        while (i >= 0 && e < L.elem[i]) {
            i--;
        }
        for (j = L.length - 1; j >= i + 1; j--) {//从最后一个元素开始向后移动一个位置
            L.elem[j + 1] = L.elem[j];
        }
        L.elem[i + 1] = e;
        L.length++;
        return 0;
    }
}

//建立递增有序的顺序表
void CreateList_Sorted(SqList &L) {
    int i, num;
    ElemType e;
    L.length = 0;
    printf("建立递增有序的顺序表,请输入数据个数:\n");
    scanf("%d", &num);
    printf("请输入%d个数据:\n", num);
    for (i = 1; i <= num; i++) {
        scanf("%d", &e);
        ListInsert(L, e);
    }
}

/*建立顺序表*/
int CreateList_Sq(SqList &L) {
    int n, i;
    printf("请输入顺序表长度:");
    scanf("%d", &n);
    if (InitList(L, n)) {
        printf("请输入%d个元素:", n);
        for (i = 0; i < n; i++) {
            scanf("%d", &L.elem[i]);
            L.length++;
        }
        return 1;
    } else
        return 0;
}

/*输出顺序表*/
void PrintList_Sq(SqList L) {
    int i;
    printf("顺序表中元素为:\n");
    for (i = 0; i < L.length; i++) {
        printf("%d ", L.elem[i]);
    }
    printf("\n");
}

//顺序查找
int ShunXu(SqList L, ElemType e) {
    int i;
    for (i = 0; i < L.length; i++)
        if (*(L.elem + i) == e)
            return i;
    return -1;
}

//有序表的二分查找
int ZheBanFeiDiGui(SqList L, ElemType key) {
    int low = 0, high = L.length - 1, mid;
    while (low < high) {
        mid = (low + high) / 2;
        if (L.elem[mid] == key) {
            return mid;
        } else if (L.elem[mid] > key) {
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }
    return -1;

}

//折半查找递归
int ZheBanDiGui(SqList L, int low, int high, KeyType K)//递归法
{//在 A[low] ~ A[high]区间进行查找,low、high初值分别为 0 和 n-1
    if (low <= high) {
        int mid = (low + high) / 2; //求中点元素下标
        if (K == L.elem[mid])
            return mid;
        else if (K < L.elem[mid])
            return ZheBanDiGui(L, low, mid - 1, K);
        else
            return ZheBanDiGui(L, mid + 1, high, K);
    } else
        return -1; //查找失败
}

//哈希查找
//int SearchHash(HashTable HT,KeyType){
//    H0=H(key);
//    if(HT[H0].key==NULLKEY)return -1;
//    if (HT[H0].key==key) return H0;
//    for (int i = 1; i < m; ++i) {
//        Hi=(H0+i)%m;
//        if (HT[Hi].key==NULLKEY)return -1;
//        if (HT[Hi].key==key)return Hi;
//    }
//    return -1;
//}
//哈希函数(除留余数法)




void menu() {
    printf("\t选择:\n");
    printf("1.顺序表的顺序查找\n");
    printf("2.顺序表的二分查找(递归和非递归)\n");
    printf("3.哈希查找\n");
    printf("0.退出\n");
}

int Hash(int data, int HASHSIZE) {
    return data % HASHSIZE;
}

void Init(HashTable *hashTable, int HASHSIZE) {
    int i;
    hashTable->elem = (int *) malloc(HASHSIZE * sizeof(int));
    hashTable->count = HASHSIZE;
    for (i = 0; i < HASHSIZE; i++) {
        hashTable->elem[i] = NULLKEY1;
    }
}//12 19 32 1 20 37 83 9 3 54 7 89 -1
//哈希表的插入函数,可用于构造哈希表
void Insert(HashTable *hashTable, int data, int HASHSIZE) {
    int hashAddress = Hash(data, HASHSIZE); //求哈希地址
    //发生冲突
    while (hashTable->elem[hashAddress] != NULLKEY1) {
        //利用开放定址法解决冲突
        ++hashAddress;
        hashAddress %= HASHSIZE;
    }
    hashTable->elem[hashAddress] = data;
}

int SearchHash(HashTable *hashTable, int data, int HASHSIZE) {
    int hashAddress = Hash(data, HASHSIZE); //求哈希地址
    while (hashTable->elem[hashAddress] != data) {//发生冲突
        //利用开放定址法解决冲突
        ++hashAddress;
        hashAddress %= HASHSIZE;
        //如果查找到的地址中数据为NULL,或者经过一圈的遍历回到原位置,则查找失败
        if (hashTable->elem[hashAddress] == NULLKEY1 || hashAddress == Hash(data, HASHSIZE)) {
            return -1;
        }
    }
    return hashAddress;
}


void SearchTest(int HASHSIZE) {
    int i = 0, result, data,flag=0;
    HashTable HT;
    int *arr = NULL;
    printf("请输入元素(-1结束)且数量不大于%d:", HASHSIZE);
    arr = (int *) malloc(sizeof(int) * HASHSIZE);
    while (1) {
        scanf("%d", &arr[i]);
        flag=flag>arr[i]?flag:arr[i];
        if (arr[i] == -1) {
            arr[i] = 0;
            break;
        }
        i++;
    }
    //初始化哈希表
//    int arr[HASHSIZE]={13,29,27,28,26,30,38};
    Init(&HT, HASHSIZE);
    //利用插入函数构造哈希表
    for (i = 0; i < HASHSIZE; i++) {
        Insert(&HT, arr[i], HASHSIZE);
    }
    for (int j = 0; j < HASHSIZE; ++j) {
        if (HT.elem[j]>flag||(j>0&& HT.elem[j]==0)) HT.elem[j]=-1;
        printf("%d\t", HT.elem[j]);
    }printf("\n");
    printf("请输入需要查找的数: ");
    scanf("%d", &data);
    result = SearchHash(&HT, data, HASHSIZE);
    if (result == -1)
        printf("查找失败\n");
    else
        printf("%d在哈希表中的位置是:%d\n", data, result);
}

void XianXingTanCe() {
    printf("请输入序列数量:n和余数:p\n");
    int i, n, *a, p;
    HashTable hashTable;
    //double k;
    scanf("%d%d", &n, &p);
    //L = (int)(1.0*n / k);
    a = (int *) malloc((n + 9) * sizeof(int));
    hashTable.elem = (int *) malloc((p + 9) * sizeof(int));
    printf("然后输入%d个数:\n", n);
    for (i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    int sum = 0;
    for (i = 0; i <= p; i++) hashTable.elem[i] = -1;
    for (i = 1; i <= n; i++) {
        int key = a[i] % p, num = 1;
        while (hashTable.elem[key] != -1) {
            num++;
            key = (key + 1) % p;
        }
        sum += num;
        hashTable.elem[key] = a[i];
    }
    printf("散列表\n");
    for (i = 0; i < p; i++)
        printf("%d%c", hashTable.elem[i], (i == p - 1) ? '\n' : ' ');
    printf("平均查找长度(成功)\n");
    if (sum % n == 0)
        printf("%d\n", sum / n);
    else {
        int g = __gcd(sum, n);
        printf("%d/%d\n", sum / g, n / g);
    }
}


void LianDiZhi() {
    printf("请输入序列数量:n和余数:p:\n");
    int n, i, j, *a, p;
    HashTable hashTable;
    hashTable.elem = (int *) malloc(sizeof(int) << 7);
    hashTable.elem[0] = 0;
    for (i = 1; i <= 100; i++)
        hashTable.elem[i] = hashTable.elem[i - 1] + i;
    scanf("%d%d", &n, &p);
    a = (int *) malloc((n + 9) * sizeof(int));
    vector<int> mp[n + 9];
    printf("然后输入%d个数:\n", n);
    for (i = 1; i <= n; i++) scanf("%d", &a[i]);
    int sum = 0;
    for (i = 1; i <= n; i++) {
        int key = a[i] % p;
        mp[key].push_back(a[i]);
    }

    printf("散列表\n");
    for (i = 1; i <= n; i++) {
        int num = mp[i].size();
        for (j = 0; j < num; j++)
            printf("%d%c", mp[i][j], (j == num - 1) ? '\n' : ' ');
        sum += hashTable.elem[num];
    }
    printf("平均查找长度(成功)\n");
    if (sum % n == 0)
        printf("%d\n", sum / n);
    else {
        int g = __gcd(sum, n);
        printf("%d/%d\n", sum / g, n / g);
    }
}

int main() {
    while (1) {
        menu();
        int choice = 0;
        int loc, key1, key2;
        int sel;
        int HASHSIZE;
        scanf("%d", &choice);
        switch (choice) {
            case 1:
                SqList L1;
                InitList(L1, 100);
                CreateList(L1);
                PrintList_Sq(L1);
                printf("请输入需要查找的值:\n");
                scanf("%d", &key1);
                loc = ShunXu(L1, key1);
                if (loc == -1) printf("表中不存在%d\n", key1);
                else printf("%d在表中的位置是:%d\n", key1, loc);
                break;
            case 2:
                SqList L2;
                InitList(L2, 100);
                CreateList_Sorted(L2);
                PrintList_Sq(L2);
                printf("请输入需要查找的值:");
                scanf("%d", &key2);
                printf("1.递归:\n");
                loc = ZheBanDiGui(L2, 0, L2.length, key2);
                if (loc == -1) printf("表中不存在%d\n", key2);
                else printf("%d在表中的位置是:%d\n", key2, loc);
                printf("2.非递归:\n");
                loc = ZheBanFeiDiGui(L2, key2);
                if (loc == -1) printf("表中不存在%d\n", key2);
                else printf("%d在表中的位置是:%d\n", key2, loc);
                break;
            case 3:
                printf("\t1.哈希函数及线性探测法生成哈希表\n");
                printf("\t2.链地址法处理冲突生成哈希表\n");
                printf("\t3.Hash查找表中具体数据\n");
                printf("\t4.退出\n");
                scanf("%d", &sel);
                switch (sel) {
                    case 1:
                        XianXingTanCe();
                        break;
                    case 2:
                        LianDiZhi();
                        break;
                    case 3:
                        printf("请输入Hash表大小:");
                        scanf("%d", &HASHSIZE);
                        SearchTest(HASHSIZE);
                        break;
                    case 4:
                        if (sel == 3) return 0;
                        else break;
                }
            case 0:
                if (choice == 0) return 0;
                else break;
        }
    }
}
posted @ 2022-06-30 14:12  WEIWEI1095  阅读(89)  评论(0)    收藏  举报
*/
作品集 //