惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
云风的 BLOG
云风的 BLOG
小众软件
小众软件
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 司徒正美
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
美团技术团队
宝玉的分享
宝玉的分享
量子位
V
Visual Studio Blog
罗磊的独立博客
Vercel News
Vercel News
B
Blog
J
Java Code Geeks
S
SegmentFault 最新的问题
Recent Announcements
Recent Announcements
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
GbyAI
GbyAI
G
Google Developers Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Set Data Structure in C
João Godinho · 2026-04-25 · via DEV Community
Cover image for Set Data Structure in C

João Godinho

  • In this article I will show how to implement a Set data structure in C using a hashtable, and discuss complexity, trade-offs, and possible improvements.

Prerequisites:

  • Basic knowledge of programming (logic, etc);
  • C syntax, allocating variables;
  • Memory management in C: pointers, malloc, free;
  • Basic understanding of hashing;

What is a Set?

  • A data structure that stores unique elements.
  • Same idea as in set theory in mathematics: no repeated values are allowed.

Why use a Hashtable?

  • A hashtable is a good choice for implementing a Set:
    • insert, find, remove -> O(1) average
  • Collisions can happen, so we need a strategy to handle them.

Collision Handling (Chaining)

  • In this implementation, collisions are handled using a linked list per bucket.
  • Multiple elements that hash to the same index are stored in the same list.

Complexity

  • Let:

    • m = number of buckets
    • k = elements in one bucket
    • n = total elements
  • Worst case:

    • insert O(k)
    • find O(k)
    • remove O(k)
    • iterate O(m + n)
    • isEmpty O(1)
  • Average case:

    • insert O(1)
    • find O(1)
    • remove O(1)
    • iterate O(m + n) -> O(n) if m is constant
    • isEmpty O(1)

Trade-offs and Improvements

  • Load factor not handled:

    • I haven't handled load factor by rehashing since the focus is the Set itself.
    • This can degrade performance as n grows.
    • Improvement: dynamic resizing (grow/shrink).
  • Hashtable vs Balanced Binary Search Tree (BST):

    • A hashtable is generally better for unordered sets, because it provides constant-time average performance and does not maintain order.
    • A balanced BST is preferable only when worst-case guarantees or sorted order are more important than average performance.
    • A set is an unordered data structure, so using a hashtable is preferable.
  • Time complexity comparison (insert, find, remove):

    • Hashtable:
    • Average case: O(1)
    • Worst case: O(n)
    • Balanced BST:
    • Average case: O(log n)
    • Worst case: O(log n)

How to Develop a Set in C

  • In this code:
    • A hashtable with fixed size is used
    • Collisions are handled with linked lists (chaining)
    • FNV-1a is used as the hash function
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SET_LIMIT_SIZE 1000

typedef struct SetNode {
  struct SetNode* next;
  int value;
} SetNode;

typedef struct Set {
  SetNode** nodes;
  int currLength;
} Set;

// 32-bit FNV-1a
unsigned int fnv1a_int(int value) {
  unsigned int hash = 2166136261u;
  unsigned char* p = (unsigned char*)&value;

  for(int i = 0; i < (int)sizeof(int); i++) {
    hash ^= (unsigned int)p[i];
    hash *= 16777619u;
  }

  return hash;
}

int itemIndex(int value, int arrLimit) {
  unsigned int hash = fnv1a_int(value);
  return hash % arrLimit;
}

Set* initializeSet() {
  Set* set = malloc(sizeof(Set));
  set->currLength = 0;
  set->nodes = malloc(sizeof(SetNode*) * SET_LIMIT_SIZE);

  for(int i = 0; i < SET_LIMIT_SIZE; i++) {
    set->nodes[i] = NULL;
  }

  return set;
}

SetNode* createNode(int value) {
  SetNode* newNode = malloc(sizeof(SetNode));
  newNode->next = NULL;
  newNode->value = value;
  return newNode;
}

void insert(Set* set, int value) {
  int index = itemIndex(value, SET_LIMIT_SIZE);
  SetNode* currentNode = set->nodes[index];

  SetNode* prevNode = NULL;
  while(currentNode != NULL) {
    if(currentNode->value == value) {
      printf("set do not allow repeated values: %d\n", value);
      return;
    }
    prevNode = currentNode;
    currentNode = currentNode->next;
  }

  SetNode* newNode = createNode(value);
  set->currLength += 1;

  if(prevNode == NULL) {
    set->nodes[index] = newNode;
  } else {
    prevNode->next = newNode;
  }
}

int isEmpty(Set* set) {
  return set->currLength == 0;
}

SetNode* find(Set* set, int value) {
  if(isEmpty(set))
    return NULL;

  int index = itemIndex(value, SET_LIMIT_SIZE);
  SetNode* currNode = set->nodes[index];

  while(currNode != NULL && currNode->value != value) {
    currNode = currNode->next;
  }

  return currNode;
}

int removeItem(Set* set, int value) {
  if(isEmpty(set))
    return -1;

  int index = itemIndex(value, SET_LIMIT_SIZE);
  SetNode* currentNodeToDelete = set->nodes[index];

  SetNode* prevNode = NULL;
  while(currentNodeToDelete != NULL && currentNodeToDelete->value != value) {
    prevNode = currentNodeToDelete;
    currentNodeToDelete = currentNodeToDelete->next;
  }

  if(currentNodeToDelete == NULL)
    return -1;

  if(prevNode != NULL) {
    prevNode->next = currentNodeToDelete->next;
  } else {
    set->nodes[index] = currentNodeToDelete->next;
  }

  free(currentNodeToDelete);
  set->currLength -= 1;

  return 1;
}

int main() {
  Set* set = initializeSet();

  printf("== insert 10, 20, 30, 10 ==\n");
  insert(set, 10);
  insert(set, 20);
  insert(set, 30);
  insert(set, 10);  // duplicate test

  printf("== find ==\n");
  printf("find 10: %s\n", find(set, 10) ? "found" : "not found");
  printf("find 99: %s\n", find(set, 99) ? "found" : "not found");

  printf("== remove ==\n");
  printf("remove 99: %d\n", removeItem(set, 99));
  printf("remove 20: %d\n", removeItem(set, 20));
  printf("remove 10: %d\n", removeItem(set, 10));
  printf("remove 10 again: %d\n", removeItem(set, 10));

  printf("== final finds ==\n");
  printf("find 10: %s\n", find(set, 10) ? "found" : "not found");
  printf("find 20: %s\n", find(set, 20) ? "found" : "not found");
  printf("find 30: %s\n", find(set, 30) ? "found" : "not found");

  return 0;
}

Enter fullscreen mode Exit fullscreen mode

References