当前位置: 首页 > news >正文

数据结构 哈希表、栈的应用与链式队列 6.29 (尾)

前言

        来到这一篇博客,数据结构的这一阶段的学习也走向尾声。

        这一篇有三个内容:哈希表(通过链地址法处理哈希冲突),括号匹配(运用栈的特性进行实现),以及链式队列的实现。

概述

        1.哈希表

        2.括号匹配

        3.链式列队

1.哈希表

1.0 基本理论

        由于直接定址法在存储数据时由于数据不连续,容易导致浪费空间的现象。因此采用除留余数法。散列函数为:H(key)=key/p,p一般取数据长度除0.75之后的最接近的质数。

        但由于会出现多个数除留余数相等的情况,即哈希冲突。此时我们通过建立链表解决哈希冲突,如下图所示:

       

        之后是代码实现:

1.1.makefile

EXE=01_hash
Objs=$(patsubst %.c,%.o,$(wildcard *.c))
CC=gcc
CFlags=-c -oall:$(EXE)
$(EXE):$(Objs)$(CC) $^ -o $@
%.o:%.c$(CC) $^ $(CFlags) $@#伪目标
.PHONY:clean
clean:rm $(EXE) $(Objs)

1.2.hash.h

#ifndef _HEAD_H_
#define _HEAD_H_#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 10
#define DEV 13typedef struct HashNode{union{int data;int len;};int result;struct HashNode* next;
}node,*node_p;typedef struct HashTable{node_p arr[DEV];
}table,*table_p;//fun
node_p create_head(int result);
node_p create_node(int value);
table_p create_Hash();
void sign_in_Hash(table_p T, int value);
void check(table_p T, int value);
void output(table_p T);#endif

1.3.fun.c

#include "hash.h"
//1
node_p create_head(int result){node_p H = (node_p)malloc(sizeof(node));H->len = 0;H->result = result;H->next = NULL;return H;
}
//2
node_p create_node(int value){node_p H = (node_p)malloc(sizeof(node));H->data = value;H->next = NULL;return H;
}
//3
table_p create_Hash(int len){if(len>MAX){printf("error\n");return NULL;}table_p H = (table_p)malloc(sizeof(table));for(int i = 0; i<=DEV-1; ++i){H->arr[i] = create_head(i);}return H;
}
//4
void sign_in_Hash(table_p T, int value){if(T == NULL){printf("error\n");return;}int result = value%13;for(int i = 0; i<=DEV-1; ++i){if(T->arr[i]->result == result){node_p new_p = create_node(value);node_p p = T->arr[i];p->len++;if(p->next!=NULL){new_p->next = p->next;}p->next = new_p;break;}}return;
}
//5
void check(table_p T, int value){if(T == NULL){printf("error\n");return;}int result = value%13;int flag = 0;node_p p = T->arr[result];while(p!=NULL){if(p->data == value){printf("exist\n");flag = 1;break;}p = p->next;}if(flag==0){printf("none\n");}return;
}
//6
void output(table_p T){if(T == NULL){printf("error\n");return;}for(int i = 0; i<=DEV-1; ++i){node_p p = T->arr[i]->next;while(p!=NULL){printf("%d ",p->data);p = p->next;}}printf("\n");return;
}

1.4.main.c

#include "hash.h"
int main(int argc, const char *argv[])
{int arr_start[10] = {25,51,8,22,26,67,11,16,54,41};table_p H = create_Hash(10);for(int i = 0; i<=9; ++i){sign_in_Hash(H,arr_start[i]);}check(H,22);output(H);free(p);p = NULL;return 0;
}

1.5.run

ubuntu@ubuntu:~/data_structre/vacation/hash$ ./01_hash 
exist
26 41 54 67 16 8 22 11 51 25 
ubuntu@ubuntu:~/data_structre/vacation/hash$ 

        对照上分图片,数据已经按哈希表的顺序排列好,数据的存入与查找也运作正常。

2.括号匹配(栈)

2.1.makefile

EXE=01_bracket
Objs=$(patsubst %.c,%.o,$(wildcard *.c))
CC=gcc
CFlags=-c -oall:$(EXE)
$(EXE):$(Objs)$(CC) $^ -o $@
%.o:%.c$(CC) $^ $(CFlags) $@#伪目标
.PHONY:clean
clean:rm $(EXE) $(Objs)

2.2.bracket.h

#ifndef _HEAD_H_
#define _HEAD_H_#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 128typedef struct stack{char arr[MAX];int top;
}stack,*stack_p;//fun
stack_p create_stack();
void input(char* str);
void match(char a,char b);
void filter(stack_p S, char*str);#endif

2.3.fun.c

#include "bracket.h"
//create stack
stack_p create_stack(){stack_p S = (stack_p)malloc(sizeof(stack));memset(S,0,sizeof(stack));S->top=-1;return S;
}//1
void input(char* str){printf("请输入需要匹配括号的字符串:\n");scanf("%s",str);str[strcspn(str,"\n")]='\0';
}
//2
void match(char a,char b){if((a=='('&&b==')')\||(a=='['&&b==']')\||(a=='{'&&b=='}')){printf("matching successed\n");}else{printf("matching failed\n");}
}
//3
void filter(stack_p S, char*str){if(S==NULL){printf("error");return;}int len = strlen(str);for(int i = 0; i<=len-1; ++i){if(str[i]=='('\||str[i]=='['\||str[i]=='{'){S->top++;S->arr[S->top]=str[i];}if(str[i]==')'\||str[i]==']'\||str[i]=='}'){match(S->arr[S->top],str[i]);S->top--;}}//puts(S->arr);return;
}

2.4.main.c

#include "bracket.h"
int main(int argc, const char *argv[])
{char str[128]={0};input(str);stack_p S = create_stack();filter(S,str);return 0;
}   

2.5.run

ubuntu@ubuntu:~/data_structre/vacation/bracket$ ./01_bracket 
请输入需要匹配括号的字符串:
(dksdhjs)[]
matching successed
matching successed
ubuntu@ubuntu:~/data_structre/vacation/bracket$ ./01_bracket 
请输入需要匹配括号的字符串:
(dhshdj[)]
matching failed
matching failed

        注意,上图中的第二种情况括号错开实际上属于匹配失败,因此试图通过对左右括号计数来判断匹配性是有问题的(不要问我怎么知道的......)

3.链式列队

3.1.makefile

EXE=01_lque
Objs=$(patsubst %.c,%.o,$(wildcard *.c))
CC=gcc
CFlags=-c -oall:$(EXE)
$(EXE):$(Objs)$(CC) $^ -o $@
%.o:%.c$(CC) $^ $(CFlags) $@#伪目标
.PHONY:clean
clean:rm $(EXE) $(Objs)

3.2.lque.h

#ifndef _HEAD_H_
#define _HEAD_H_#include <stdio.h>
#include <string.h>
#include <stdlib.h>typedef struct queue{int data;struct queue* next;
}queue,*queue_p;typedef struct head{queue_p front;queue_p rear;
}head,*head_p;head_p create_head();
queue_p create_node(int value);
void input(head_p H,int value);
int output(head_p H);
void show(head_p H);
#endif

3.3.fun.c

#include "lque.h"
//1
head_p create_head(){head_p H = (head_p)malloc(sizeof(head));H->front = NULL;H->rear = NULL;return H;
}
//2
queue_p create_node(int value){queue_p Q = (queue_p)malloc(sizeof(queue));Q->data = value;Q->next = NULL;return Q;
}
//3
//列队的特性:尾进
void input(head_p H,int value){queue_p new = create_node(value);new->next = NULL;new->data = value;if(H->rear!=NULL){H->rear->next = new;}H->rear = new;if(H->front == NULL){H->front = new;}return;
}
//4
//头出
int output(head_p H){if(H->front == NULL)return -999;queue_p p_del = H->front;H->front = H->front->next;int out_data = p_del->data;free(p_del);return out_data;
}
//5
void show(head_p H){if(H->front == NULL)return;queue_p p = H->front;while(p!=NULL){printf("%d ",p->data);p=p->next;}printf("\n");return;
}

3.4.main.c

#include "lque.h"
int main(int argc, const char *argv[])
{head_p H = create_head();input(H,1);input(H,2);input(H,3);input(H,4);input(H,5);show(H);int num = output(H);printf("output:%d\n",num);printf("after:");show(H);return 0;
}  

3.5.run

ubuntu@ubuntu:~/data_structre/vacation/linked queue$ make
gcc main.c -c -o main.o
gcc fun.c -c -o fun.o
gcc main.o fun.o -o 01_lque
ubuntu@ubuntu:~/data_structre/vacation/linked queue$ ./01_lque 
1 2 3 4 5 
output:1
after:2 3 4 5 
ubuntu@ubuntu:~/data_structre/vacation/linked queue$ .

        尾进头出。

结语

        以上。

相关文章:

  • 模拟工作队列 - 华为OD机试真题(JavaScript卷)
  • Python 数据分析与可视化 Day 11 - 特征工程基础
  • 从0开始学linux韦东山教程Linux驱动入门实验班(3)
  • python中多线程:线程插队方法join详解、线程停止、通过变量来让线程停止
  • Java面试宝典:基础五
  • 【数据集】中国2016-2022年 城市土地利用数据集 CULU
  • 操作系统学习笔记 | 操作系统常见问题整理
  • AlphaFold3安装报错
  • NumPy 统计函数与矩阵运算指南
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月29日第123弹
  • 理解 Confluent Schema Registry:Kafka 生态中的结构化数据守护者
  • 数据库级联操作详解:级联删除、更新与置空
  • aws(学习笔记第四十八课) appsync-graphql-dynamodb
  • 详解快速排序
  • STM32——HAL库总结
  • acme自签证书
  • docker安装gitlab并配置ssl证书
  • DeepSeek贪吃蛇游戏网页版
  • python打卡 DAY 46 通道注意力(SE注意力)
  • AVL树的简洁写法