一、利用链地址法解决哈希冲突
1、用于练习的结构体及宏定义(N表示元素个数,P表示哈希表长度)
#define N 10
#define P 13
typedef int datatype;
typedef struct Node
{
datatype data;
struct Node *next;
}Node;
2、主函数(用于检验子函数功能)
#include<stdio.h>
#include<stdlib.h>
#include"./hash.h"
int main(int argc, const char *argv[])
{
int arr[N]={25,51,8,22,26,67,11,16,54,14};
Node *hash[P];
//初始化哈希表
init_hash(hash);
//将元素存入哈希表
for(int i=0; i<N; i++)
{
insert_hash(hash,arr[i]);
}
//调用遍历函数
show_hash(hash);
//调用查找函数
search_hash(hash,22);
return 0;
}
3、功能函数
1)初始化哈希表
void init_hash(Node *hash[])
{
for(int i=0; i<P; i++)
{
hash[i]=NULL;
}
printf("初始化成功\n");
}
2)将元素存入哈希表
int insert_hash(Node *hash[],int x)
{
int index = x%P; //定位要存储的链表
//将数据封装成结点
Node *q =(Node *)malloc(sizeof(Node));
if(NULL==q)
{
printf("空间申请失败\n");
return -1;
}
q->data = x;
q->next = NULL;
//使用头插法将结点放入链表hash[index]
q->next = hash[index];
hash[index] = q;
return 0;
}
3)遍历查看哈希表函数
void show_hash(Node *hash[])
{
for(int i=0; i<P; i++)
{
printf("%d:",i);
//定义遍历指针
Node *q = hash[i];
while(q!=NULL)
{
printf("%d->",q->data);
q=q->next;
}
printf("NULL\n");
}
}
4)查找表中数据
void search_hash(Node *hash[],int key)
{
int index = key%P; //定位要查找的值所在链表
//定义遍历指针
Node *q =hash[index];
while(q!=NULL && q->data!=key)
{
q=q->next;
}
//对找到的结点判断
if(NULL==q)
{
printf("查找失败\n");
}else
{
printf("您要查找的数据在表中\n");
}
}
5)运行结果
初始化成功
0:26->NULL
1:14->NULL
2:54->67->NULL
3:16->NULL
4:NULL
5:NULL
6:NULL
7:NULL
8:8->NULL
9:22->NULL
10:NULL
11:11->NULL
12:51->25->NULL
表中有该数据
二、排序练习
0)实现的结果
排序前:198 289 98 357 85 170 232 110
排序后:85 98 110 170 198 232 289 357
1、冒泡排序
#include<stdio.h>
int main(int argc, const char *argv[])
{
int arr[]={198,289,98,357,85,170,232,110}; //存放数据
int temp; //交换变量
int flag=1; //判断是否已经有序
printf("排序前:");
for(int i=0; i<8; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
//冒泡排序
for(int i=1; i<8; i++)
{
for(int j=0; j<8-i; j++)
{
flag=1;
if(arr[j]>arr[j+1])
{
temp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;
flag=0;
}
}
if(flag==1) //判断是否有序
{
break;
}
}
printf("排序后:");
for(int i=0; i<8; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
return 0;
}
2)选择排序
#include<stdio.h>
int main(int argc, const char *argv[])
{
int arr[]={198,289,98,357,85,170,232,110}; //存放数据
int temp; //交换变量
int i,j; //循环变量
int index; //存放最小值下标
printf("排序前:");
for(i=0; i<8; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
//选择排序
for(i=0; i<8; i++)
{
index=i;
for(j=i; j<8; j++)
{
if(arr[index]>arr[j]) //遍历未排序数组,将最小值下标取出
{
index=j;
}
}
if(index!=i)
{
//三杯水交换
temp=arr[index];arr[index]=arr[i];arr[i]=temp;
}
}
printf("排序后:");
for(i=0; i<8; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
return 0;
}
3)插入排序
#include<stdio.h>
int main(int argc, const char *argv[])
{
int arr[]={198,289,98,357,85,170,232,110}; //存放数据
int i,j; //循环变量
int temp; //交换变量
printf("排序前:");
for(i=0; i<8; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
for(i=1; i<8; i++) //外层由元素个数控制
{
temp = arr[i]; //temp赋初值(要插入的数)
for(j=i; j>0 && temp<arr[j-1]; j--) //将要插入的数与已排序好的序列的所有元素比较找到要插入的位置
{
arr[j]=arr[j-1]; //腾空
}
arr[j] =temp; //插入
}
printf("排序后:");
for(i=0; i<8; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
return 0;
}
4、快速排序
#include<stdio.h>
int part(int arr[],int low,int high)
{
int x=arr[low]; //选定基准并腾出low下标的空间
while(low<high) //保证可以遍历所有元素
{
while(arr[high]>=x && low<high) //防止越界查找
{
high--;
}
arr[low]=arr[high]; //将小于基准的值放入数组前段
while(arr[low]<=x && low<high) //防止越界查找
{
low++;
}
arr[high]=arr[low]; //将大于基准的值放入数组后段
}
arr[low]=x; //将标准放入指定的位置
return low; //返回基准所在的位置
}
void quick_sort(int arr[],int low,int high)
{
int mid;
if(low<high)
{
mid=part(arr,low,high); //先进行一次排序,将数组由基准分为两组
quick_sort(arr,low,mid-1); //递归实现数组前段的数据有序化
quick_sort(arr,mid+1,high); //递归实现数组后段的数据有序化
}
}
int main(int argc, const char *argv[])
{
int arr[]={198,289,98,357,85,170,232,110}; //存放数据
printf("排序前:");
for(int i=0; i<8; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
quick_sort(arr,0,8); //调用快排函数
printf("调用快排后:");
for(int i=0; i<8; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
return 0;
}