数据结构(6)—哈希表、数据排序和查找

一、哈希表

1. 哈希算法:

将数据通过哈希算法映射成一个键值,存取都在同一位置实现数据的高效存储和查找,将时间复杂度尽可能降低至O(1)

2. 哈希碰撞:

多个数据通过哈希算法得到的键值相同,称为产生哈希碰撞

3. 哈希表:

构建哈希表存放0-100之间的数据

哈希算法选择:将0 - 100之间的数据的个位作为键值

4. 哈希表的实现

(1)哈希表插入

int insert_hashtable(int tmpdata)
{
    int key = 0;
    linknode **pptmpnode = NULL;
    linknode *pnewnode = NULL;
    key = tmpdata % INDEX;
    for (pptmpnode = &phashtable[key]; *pptmpnode != NULL &&(*pptmpnode)->data < tmpdata; pptmpnode = &(*pptmpnode)->pnext)
    {
    }
    pnewnode = malloc(sizeof(linknode));
    if (NULL == pnewnode)
    {
        perror("fail to malloc");
        return -1;
    }
    pnewnode->data = tmpdata;
    pnewnode->pnext = *pptmpnode;
    *pptmpnode = pnewnode;
    return 0;
}

(2)哈希表遍历

int show_hashtable(void)
{
    int i = 0;
    linknode *ptmpnode = NULL;
    for (i = 0; i < INDEX; i++)
    {
        printf("%d:", i);
        ptmpnode = phashtable[i];
        while (ptmpnode != NULL)
        {
            printf("%2d ", ptmpnode->data);
            ptmpnode = ptmpnode->pnext;
        }
    printf("\n");
    }
    return 0;
}

(3)元素查找

linknode *find_hashtable(int tmpdata)
{
    int key = 0;
    linknode *ptmpnode = NULL;
    key = tmpdata % INDEX;
    ptmpnode = phashtable[key];
    while (ptmpnode != NULL && ptmpnode->data <= tmpdata)
    {
        if (ptmpnode->data == tmpdata)
        {
            return ptmpnode;
        }
        ptmpnode = ptmpnode->pnext;
    }
    return NULL;
}

(4)哈希表销毁

int destroy_hashtable(void)
{
    int i = 0;
    linknode *ptmpnode = NULL;
    linknode *pfreenode = NULL;
    for(i = 0; i < INDEX; i++)
    {
        ptmpnode = phashtable[i];
        pfreenode = phashtable[i];
        while (ptmpnode != NULL)
        {
            ptmpnode = ptmpnode->pnext;
            free(pfreenode);
            pfreenode = ptmpnode;
        }
        phashtable[i] = NULL;
    }
    return 0;
}

二、排序和查找算法

1. 冒泡排序

时间复杂度为O(n^2)

稳定的排序算法

排序方法:相邻的两个元素比较,大的向后走,小的向前走,循环找len-1个大的值

int bubble_sort(int *parray, int len)
{
    int i = 0;
    int j = 0;
    int tmp = 0;
    for (j = 0; j < len-1; j++)
    {
        for (i = 0; i < len-1-j; i++)
        {
            if (parray[i] > parray[i+1]
            {
                tmp = parray[i];
                parray[i] = parray[i+1];
                parray[i+1] = tmp;
            }
        }
    }
    return 0;
}

2.选择排序

时间复杂度O(n^2)

不稳定排序算法

排序方法:从前到后找最小值与前面的元素交换,找到len-1个最小值,最后一个最大值即排序完成

int select_sort(int *parray, int len)
{
    int i = 0;
    int j = 0;
    int tmp = 0;
    int min = 0;
    for (j = 0; j < len-1; j++)
    {
        min = j;
        for (i = j+1; i < len; i++)
        {
            if (parray[i] < parray[min])
            {
                min = i;
            }
        }
        if (min != j)
        {
            tmp = parray[min];
            parray[min] = parray[j];
            parray[j] = tmp;
        }
    }
    return 0;
}

int insert_sort(int *parray, int len)
{
int tmp = 0;
int i = 0;
int j = 0;
for (j = 1; j < len; j++)
{
tmp = parray[j];
for (i = j; i > 0 && tmp < parray[i-1]; i--)
{
parray[i] = parray[i-1];
}
parray[i] = tmp;
}
return 0;

3. 插入排序

时间复杂度O(n^2) ,如果素组有序时间复杂度降低至O(n)

稳定的排序算法

排序方法:

将数组中的每个元素插入到有序数列中

先将要插入的元素取出

依次和前面元素比较,比元素大的向后走,直到前一个元素比要插入的元素小,或者到

达有序数列开头停止

插入元素即可

int insert_sort(int *parry, int len)
{
    int tmp = 0;
    int i = 0;
    int j = 0;

    for(j = 1; j < len; j++)
    {
        tmp = parry[j];
        for(i = j; i > 0 && parry[i-1] > tmp; i--)
        {
            parry[i] = parry[i-1];
        }
        parry[i] = tmp;
    }

    return 0;
}

int output_array(int *parray, int len)
{
    int i = 0;

    for(i = 0; i < len; i++)
    {
        printf("%d ", parray[i]);
    }
    printf("\n");

    return 0;
}

4.希尔排序

时间复杂度O(nlogn)

不稳定的排序算法

通过选择不同的步长,将数组拆分成若干个小的数组实现插入排序

若干个小的数组称为有序数列后,使得数组中的数据大致有序

最后再对整体完成一个插入排序

int shell_sort(int *parray, int len)
{
    int step = 0;
    int j = 0;
    int i = 0;
    int tmp = 0;

    for (step = len/2; step > 0; step /= 2)
    {
        for (j = step; j < len; j++)
        {
            tmp = parray[j];
            for (i = j; i >= step && tmp < parray[i-step]; i -= step)
            {
                parray[i] = parray[i-step];
            }
            parray[i] = tmp;
        }
    }

    return 0;
}

5.快速排序

时间复杂度为O(nlogn)

不稳定的排序算法

选择左边的作为键值,从后面找一个比键值小的放前面,从前面找一个比键值大的放后面,键
值放中间

左右两边有元素则递归调用快速排序

int quick_sort(int *parray, int low, int high)
{
    int key = 0;
    int j = 0;
    int i = 0;

    key = parray[low];
    j = high;
    i = low;

    while (i < j)
    {
        while (i < j && parray[j] >= key)
        {
            j--;
        }
        if (i < j)
        {
            parray[i] = parray[j];
        }
        while (i < j && parray[i] <= key)
        {
            i++;
        }
        if (i < j)
        {
            parray[j] = parray[i];
        }    
    }
    parray[i] = key;

    if (i-1 > low)
    {
        quick_sort(parray, low, i-1);
    }
    if (i+1 < high)
    {
        quick_sort(parray, i+1, high);
    }
    
    return 0;
}

6.折半查找(二分查找)

时间复杂度O(nlogn)

从数组最中间查找,如果就是要找的值输出,如果不是但这个值大于中间的值,则它后面的数递归这个函数;如果不是但这个值小于中间的值,则它前面的数递归调用这个函数

int mid_search(int *parray, int low, int high, int tmpdata)
{
    int mid = 0;

    if (low > high)
    {
        return -1;
    }

    mid = (low + high) / 2;
    if (tmpdata == parray[mid])
    {
        return mid;
    }
    else if (tmpdata > parray[mid])
    {
        return mid_search(parray, mid+1, high, tmpdata);
    }
    else if (tmpdata < parray[mid])
    {
        return mid_search(parray, low, mid-1, tmpdata);
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值