C 位字段,_Alignas关键字,可变参数函数和高级数据结构

目录

一、位字段

二、_Alignof和_Alignas关键字

三、可变参数函数

四、高级数据结构

1、双向链表

2、HashMap

3、FIFO队列

4、红黑树


一、位字段

    位字段是C语言提供的操作位的一种便捷且代码可读性更好的方式,适用于只需少量的位表示数据的场景下。GNU C下,位字段的内存大小是unsigned int类型所占内存的整数倍,64位下unsigned int类型通常是4字节,32位,即位字段最小为4字节,编译器保证位字段的内存大小大于位字段中声明的内存大小。

#include <stdio.h>
#include <stdbool.h>


//声明位字段,数字表示该字段占的位数,未命名的字段用于填充的
//位字段在内存中以unsigned int的内存大小为基本布局单位,64位下通常是4字节,32位,
//即使位字段声明的总位数小于32位,也会占用4字节内存,如果大于32位则会自动扩充位字段的
//内存大小,但保证按照4字节对齐
struct box_props {
    bool b1                 : 1;
    unsigned int b10     : 10;
//    unsigned int                : 4;
    unsigned int                : 24;
    unsigned int b3   : 3;
    unsigned int b2   : 2;
    unsigned int                : 2;
};


int main(void)
{
	printf("unsigned int size:%d \n",sizeof(unsigned int));
	printf("box_props size:%d \n",sizeof(struct box_props));

	//位字段的使用跟正常的结构体一致
    struct box_props a={1,345,7,3};
    printf("a b1:%d\n",a.b1);
    printf("a b10:%d\n",a.b10);
    printf("a b3:%d\n",a.b3);
    printf("a b2:%d\n",a.b2);
    
    //对位字段赋值时,需要确保数值不能大于该字段对应位数允许的最大值,这里是1024,超过后编译器会自动截断掉高位
    //1025的二进制是1000 0000 01,截掉高位1,就是000 0000 01
    a.b10=1025;
    printf("a b10:%d\n",a.b10);

    return 0;
}

二、_Alignof和_Alignas关键字

     _Alignof给出指定数据类型内存对齐的字节数,如double按8字节对齐,其内存地址都是8的整数倍。_Alignas关键字指定某个变量按照其他数据类型对齐,如char正常按1字节对齐,可指定按short类型的2字节对齐。

#include <stdio.h>
int main(void)
{
    int dx;
    char ca;
    char cx;
    //指定对齐的字节数必须大于本来的,这里必须大于4
//    int _Alignas(short)  dz;
    int _Alignas(double)  dz;
    char cb;
    //_Alignas要求某个变量的内存地址按指定的字节数对齐
    char _Alignas(short)  cz;
   
    //_Alignof关键字给出该类型变量的内存对齐字节数,比如double按8字节对齐,即其存储地址必须是8的整数倍
    printf("char alignment:   %zd\n", _Alignof(char));
    printf("short alignment: %zd\n", _Alignof(short));
    printf("int alignment: %zd\n", _Alignof(int));
    printf("double alignment: %zd\n", _Alignof(double));
    printf("&dx: %p\n", &dx);
    printf("&ca: %p\n", &ca);
    printf("&cx: %p\n", &cx);
    printf("&dz: %p\n", &dz);
    printf("&cb: %p\n", &cb);
    printf("&cz: %p\n", &cz);
    
    return 0;
}

三、可变参数函数

      C语言通过stdarg.h头文件提供了对可变参数函数的支持,即函数的参数的个数和类型是未知的,不过要求可变参数必须是最后一个参数,且可变参数前一个参数固定是int类型的,固定用于表示实际参数个数。

#include <stdio.h>
//必须引入这个头文件
#include <stdarg.h>
double sum(int, ...);

int main(void)
{
    double s,t;
    
    s = sum(5, 1.1, 2.5, 13.3,1,2,'c');
    t = sum(6, 1.1, 2.1, 13.1, 4.1, 5.1, 6.1);
    printf("return value for "
           "sum(3, 1.1, 2.5, 13.3,1,2,'c'):                %g\n", s);
    printf("return value for "
           "sum(6, 1.1, 2.1, 13.1, 4.1, 5.1, 6.1): %g\n", t);
    
    return 0;
}

double sum(int lim,...)
{
	//保存可变参数的列表
    va_list ap;
    double tot = 0;
    int i;
    
    //将实际参数放到列表中
    va_start(ap, lim);
    for (i = 0; i < lim; i++){
    	//返回指定类型的参数,实际参数类型不符则返回0
    	double a=va_arg(ap, double);
    	printf("va_arg i=%d,a=%f\n",i,a);
        tot += a;
    }
    //清空参数列表
    va_end(ap);
    
    return tot;
}

四、高级数据结构

    提供类型属性和相关操作的抽象描述被称为抽象数据类型(ADT),通俗的理解就是Java中的类,既有类属性也有关联的类方法,类方法通过接口的形式定义,使用方只关心接口定义不关心接口实现。

1、双向链表

     C中typedef不允许重复定义,因此只能通过void指针加上指针类型强转这种方式实现泛型的效果,最终让链表能够适用于所有数据类型。

头文件即接口定义如下:

//避免头文件重复引入
#ifndef MYLIST_H_INCLUDED
#define MYLIST_H_INCLUDED
#include <stdio.h>


typedef struct myNode
{
	//用void指针实现泛型效果
    void * data;
    struct myNode *next;
} MyNode;

typedef struct myList
{
    MyNode * first;
    MyNode * last;
    int count; //链表总结点数
    int (*equal)(void * a, void * b);
} MyList;

typedef struct myListIterator
{
    MyNode * p;
    int count; //当前遍历的链表节点索引
    int allSize; //链表节点总数
} MyListIterator;

//创建链表
MyList * createMyList();

//创建链表,带有相等参数,用于查找
MyList * createMySearchList(int(*equal)(void * a, void * b));

//释放链表
void freeMyList(MyList * list);

//插入在尾部
void myListInsertDataAtLast(MyList* const list, void* const data);

//插入在首部
void myListInsertDataAtFirst(MyList * const list, void* const data);

//插入
void myListInsertDataAt(MyList * const list, void* const data, int index);

//删除在尾部
void* myListRemoveDataAtLast(MyList* const list);

//删除在首部
void* myListRemoveDataAtFirst(MyList * const list);

//删除
void* myListRemoveDataAt(MyList* const list, int index);

//删除对象,返回是否删除成功
int myListRemoveDataObject(MyList* const list, void * data);

//长度
int myListGetSize(const MyList * const list);

//打印
void myListOutput(const MyList * const list, void(*pt)(const void * const));

//取得数据
void* myListGetDataAt(const MyList * const list, int index);

//取得第一个数据
void* myListGetDataAtFirst(const MyList * const list);

//取得最后一个数据
void* myListGetDataAtLast(const MyList * const list);

//查找某个数据的位置,如果equal方法为空,比较地址,否则调用equal方法
//如果不存在返回-1,如果存在,返回出现的第一个位置
int myListFindDataIndex(const MyList * const list, void * data);

//创建遍历器
MyListIterator* createMyListIterator(const MyList * const list);

//释放遍历器
void freeMyListIterator(MyListIterator* iterator);

//遍历器是否有下一个元素
int myListIteratorHasNext(const MyListIterator* const iterator);

//返回遍历器的下一个元素
void * myListIteratorNext(MyListIterator* const iterator);

#endif // MYLIST_H_INCLUDED


接口实现如下:

#include "myList.h"
#include <stdlib.h>
//创建链表
MyList * createMyList()
{
    MyList * re = (MyList *) malloc(sizeof(MyList));
    re->count = 0;
    re->first = NULL;
    re->last = NULL;
    re->equal = NULL;
    return re;
}

//释放链表
void freeMyList(MyList * list)
{
    MyNode * p;
    while (list->first)
    {
        p = list->first->next;
        free(list->first);
        list->first = p;
    }
    free(list);
}

//插入在尾部
void myListInsertDataAtLast(MyList * const list, void* const data)
{
    MyNode * node = (MyNode *) malloc(sizeof(MyNode));
    node->data = data;
    node->next = NULL;
    if (list->count)
    {
        list->last->next = node;
        list->last = node;
    }
    else
    {
        list->first = node;
        list->last = node;
    }
    (list->count)++;
}

//插入在首部
void myListInsertDataAtFirst(MyList * const list, void* const data)
{
    MyNode * node = (MyNode *) malloc(sizeof(MyNode));
    node->data = data;
    node->next = NULL;

    if (list->count)
    {
        node->next = list->first;
        list->first = node;
    }
    else
    {
        list->first = node;
        list->last = node;
    }
    (list->count)++;
}

//长度
int myListGetSize(const MyList * const list)
{
    return list->count;
}

//打印
void myListOutput(const MyList * const list, void(*pt)(const void * const))
{
    MyNode * p = list->first;
    while (p)
    {
        (*pt)(p->data);
        p = p->next;
    }
}

//删除在尾部
void* myListRemoveDataAtLast(MyList* const list)
{
    if (list->count == 1)
    {
        return myListRemoveDataAtFirst(list);
    }
    MyNode * p = list->first;
    while (p->next != list->last)
    {
        p = p->next;
    }
    void *re = list->last->data;
    free(list->last);
    p->next = NULL;
    list->last = p;
    (list->count)--;
    return re;
}

//删除在首部
void* myListRemoveDataAtFirst(MyList * const list)
{
    MyNode *p = list->first;
    list->first = p->next;
    void * re = p->data;
    free(p);
    (list->count)--;
    if (list->count == 0)
    {
        list->last = NULL;
    }
    return re;
}

//插入
void myListInsertDataAt(MyList * const list, void* const data, int index)
{
    if (index == 0)
    {
        myListInsertDataAtFirst(list, data);
        return;
    }
    if (index == list->count)
    {
        myListInsertDataAtLast(list, data);
        return;
    }
    MyNode * node = (MyNode *) malloc(sizeof(MyNode));
    node->data = data;
    node->next = NULL;

    MyNode * p = list->first;
    for (int i = 0; i < index - 1; i++)
    {
        p = p->next;
    }
    node->next = p->next;
    p->next = node;

    (list->count)++;
}

//删除
void* myListRemoveDataAt(MyList* const list, int index)
{
    if (index == 0)
    {
        return myListRemoveDataAtFirst(list);
    }
    if (index == list->count - 1)
    {
        return myListRemoveDataAtLast(list);
    }

    MyNode * p = list->first;
    for (int i = 0; i < index - 1; i++)
    {
        p = p->next;
    }
    MyNode *tp = p->next;
    p->next = p->next->next;
    void * re = tp->data;
    free(tp);
    (list->count)--;
    return re;
}

//取得数据
void* myListGetDataAt(const MyList * const list, int index)
{
    if (index == list->count - 1)
    {
        return myListGetDataAtLast(list);
    }
    MyNode * p = list->first;
    for (int i = 0; i < index; i++)
    {
        p = p->next;
    }
    return p->data;
}

//取得第一个数据
void* myListGetDataAtFirst(const MyList * const list)
{
    return list->first->data;
}

//取得最后一个数据
void* myListGetDataAtLast(const MyList * const list)
{
    return list->last->data;
}

//查找某个数据的位置,如果equal方法为空,比较地址,否则调用equal方法
//如果不存在返回-1,如果存在,返回出现的第一个位置
int myListFindDataIndex(const MyList * const list, void * data)
{
    MyNode * p = list->first;
    int re = 0;
    if (list->equal)
    {
        while (p)
        {
            if (p->data == data || (*(list->equal))(p->data, data))
            {
                return re;
            }
            re++;
            p = p->next;
        }

    }
    else
    {
        while (p)
        {
            if (p->data == data)
            {
                return re;
            }
            re++;
            p = p->next;
        }
    }
    return -1;
}

//创建链表,带有相等参数,用于查找
MyList * createMySearchList(int(*equal)(void * a, void * b))
{
    MyList * re = createMyList();
    re->equal = equal;
    return re;
}

//创建遍历器
MyListIterator* createMyListIterator(const MyList * const list)
{
    MyListIterator * re = (MyListIterator *) malloc(sizeof(MyListIterator));
    re->p = list->first;
    re->allSize = list->count;
    re->count = 0;
    return re;
}

//释放遍历器
void freeMyListIterator(MyListIterator* iterator)
{
    free(iterator);
}

//遍历器是否有下一个元素
int myListIteratorHasNext(const MyListIterator* const iterator)
{
    return iterator->count < iterator->allSize;
}

//返回遍历器的下一个元素
void * myListIteratorNext(MyListIterator* const iterator)
{
    void * re = iterator->p->data;
    iterator->p = iterator->p->next;
    (iterator->count)++;
    return re;
}

//删除对象,返回是否删除成功
int myListRemoveDataObject(MyList* const list, void * data)
{
    MyListIterator * it = createMyListIterator(list);
    int a = 0;
    while (myListIteratorHasNext(it))
    {
        void * ld = myListIteratorNext(it);
        if (data == ld || (list->equal != NULL && (*(list->equal))(ld, data)))
        {
            a = 1;
            break;
        }
    }
    if (a)
    {
        myListRemoveDataAt(list, it->count - 1);
    }
    return a;
}

测试用例如下:


#include <stdio.h>
#include <stdlib.h>
#include "myList.h"

typedef struct a
{
    int i;
    char c;
} A;

//打印函数
void ppt(const void* const p)
{
	//指针类型强转
    A * pp= (A*)p;
    printf("%d(%c) ", pp->i, pp->c);
}


int main()
{
    const int S =10;

    //创建并初始化数据
    A * data= malloc(sizeof(A)*S);
    for (int i=0; i< S; i++)
    {
        data[i].i=i;
        data[i].c=(char)('A'+i);
    }

    //创建链表
    MyList * list= createMyList();

    //测试三种插入方法
    myListInsertDataAtLast( list, &data[0]);
    myListInsertDataAtFirst( list, &data[4]);
    myListInsertDataAt(list, &data[1], 1 );


    //测试查找
    int index = myListFindDataIndex(list, &data[2]);
    printf("%d\n", index);
    index = myListFindDataIndex(list, &data[4]);
    printf("%d\n", index);

    //输出
    myListOutput(list, ppt );
    puts("");

    //测试使用迭代器输出
    MyListIterator * it = createMyListIterator(list);
    while(myListIteratorHasNext(it))
    {
        A * pp = myListIteratorNext(it);
        printf("%d[%c] ", pp->i, pp->c);
    }
    puts("");
    //释放迭代器
    freeMyListIterator(it);

    //释放链表
    freeMyList(list);

    //释放数据
    free(data);
    return 0;
}

2、HashMap

     HashMap的实现基于数组加链表,每个数组元素保存链表指针,链表保存相同hash值的多个键值对,跟Java HashMap的实现一样。

头文件如下:

#ifndef MYHASHMAP_H_INCLUDED
//HashMap的实现基于数组加链表,每个数组元素保存链表指针,链表保存相同hash值的多个键值对,
//跟Java HashMap的实现一样
#define MYHASHMAP_H_INCLUDED
#include "myList.h"

#define DEFAULT_INITIAL_CAPACITY 16
#define DEFAULT_LOAD_FACTOR 0.75f

typedef struct entry
{
	//通过void指针实现泛型效果
    void * key;
    void * value;
} Entry;

typedef struct myHashMap
{
    int size;   //大小
    int initialCapacity; //初始容量
    float loadFactor;   //加载因子
    int (*hashCode)(void *key);
    int (*equal)(void *key1,void *key2);
    MyList ** entryList;//这里是保存MyList指针的数组的指针
} MyHashMap;

typedef struct myHashMapEntryIterator
{
    int index;       //第几个链表
    MyHashMap *map;
    MyNode *current;
    int count;        //第几个数据
} MyHashMapEntryIterator;

//创建HashMap
MyHashMap *createMyHashMap(int (*hashCode)(void *key),int (*equal)(void *key1,void *key2));

//使用全部参数创建HashMap
MyHashMap *createMyHashMapForAll(int initialCapacity,float loadFactor,int (*hashCode)(void *key),int (*equal)(void *key1,void *key2));

//释放HashMap
void freeMyHashMap(MyHashMap * map);

//是否包含某个key
int myHashMapContainsKey(MyHashMap *const map,void * const key);

//增加一条映射
void myHashMapPutData(MyHashMap *const map,void * const key,void * const value);

//通过key得到数据,如果没有数据则返回null
void* myHashMapGetDataByKey(MyHashMap * const map,void *const key);

//数据的容量
int myHashMapGetSize(const MyHashMap * const map);

//创建Entry迭代器
MyHashMapEntryIterator* createMyHashMapEntryIterator( MyHashMap *const map);

//释放Entry迭代器
void freeMyHashMapEntryIterator(MyHashMapEntryIterator* iterator);

//Entry迭代器是否有下一个
int myHashMapEntryIteratorHasNext(MyHashMapEntryIterator* iterator);

//遍历下一个Entry元素
Entry* myHashMapEntryIteratorNext(MyHashMapEntryIterator* iterator);

//删除一条数据,返回是否删除成功
int myHashMapRemoveDataByKey(MyHashMap *const map,void * const key);

//遍历
void myHashMapOutput(MyHashMap *map, void(*pt)(Entry*));

#endif // MYHASHMAP_H_INCLUDED

具体实现如下:

#include "myHashMap.h"
#include <stdlib.h>

static void initEntryList(MyHashMap * const map);

//某条Entry链表上是否包含某个key值。
Entry* listContainsEntry(MyList * list, void * key,
		int (*equal)(void *key1, void *key2)) {
	MyListIterator* it = createMyListIterator(list);
	while (myListIteratorHasNext(it)) {
		Entry * entry = (Entry *) (myListIteratorNext(it));
		if (entry->key == key || (equal != NULL && (*equal)(entry->key, key))) {
			return entry;
		}
	}
	freeMyListIterator(it);
	return NULL;
}

void rebuildMyHashMap(MyHashMap * map) {
	int newSize = map->initialCapacity * 2;
	//初始化扩容后的数组
	MyList **newentryList = (MyList **) malloc(sizeof(MyList*) * newSize);
	for (int i = 0; i < newSize; i++) {
		newentryList[i] = createMyList();
	}
	//遍历所有的元素,插入到扩容后的数组中
	MyHashMapEntryIterator* it = createMyHashMapEntryIterator(map);
	while (myHashMapEntryIteratorHasNext(it)) {
		Entry * entry = myHashMapEntryIteratorNext(it);
		int hasCode = (*(map->hashCode))(entry->key);
		hasCode %= newSize;
		if (hasCode < 0)
			hasCode += newSize;
		myListInsertDataAtLast(newentryList[hasCode], entry);
	}
	freeMyHashMapEntryIterator(it);
	//释放旧链表
	for (int i = 0; i < map->initialCapacity; i++) {
		freeMyList(map->entryList[i]);
	}
	free(map->entryList);
	map->entryList = newentryList;
	map->initialCapacity = newSize;
}

//创建HashMap
MyHashMap *createMyHashMap(int (*hashCode)(void *key),
		int (*equal)(void *key1, void *key2)) {
	return createMyHashMapForAll(DEFAULT_INITIAL_CAPACITY,DEFAULT_LOAD_FACTOR,hashCode,equal);
}

//使用全部参数创建HashMap
MyHashMap *createMyHashMapForAll(int initialCapacity, float loadFactor,
		int (*hashCode)(void *key), int (*equal)(void *key1, void *key2)) {
	MyHashMap *re = (MyHashMap *) malloc(sizeof(MyHashMap));
	re->size = 0;
	re->initialCapacity = initialCapacity;
	re->loadFactor = loadFactor;
	re->hashCode = hashCode;
	re->equal = equal;
	initEntryList(re);
	return re;
}


static void initEntryList(MyHashMap * const map) {
	map->entryList = (MyList **) malloc(sizeof(MyList*) * map->initialCapacity);
	//初始化所有保存MyList指针的数组元素
	for (int i = 0; i < map->initialCapacity; i++) {
		map->entryList[i] = createMyList();
	}
}

//是否包含某个key
int myHashMapContainsKey(MyHashMap * const map, void * const key) {
	int hasCode = (*(map->hashCode))(key);
	hasCode %= map->initialCapacity;
	if (hasCode < 0)
		hasCode += map->initialCapacity;
	Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal);
	return re != NULL;
}

//增加一条映射
void myHashMapPutData(MyHashMap * const map, void * const key,
		void * const value) {
	//计算key的存储位置
	int hasCode = (*(map->hashCode))(key);
	hasCode %= map->initialCapacity;
	if (hasCode < 0)
		hasCode += map->initialCapacity;
	//该key是否已存在
	Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal);
	if (re == NULL) {//不存在则插入
		Entry * entry = (Entry*) malloc(sizeof(Entry));
		entry->key = key;
		entry->value = value;
		myListInsertDataAtLast(map->entryList[hasCode], entry);
		(map->size)++;
		//大于设定容量,自动扩容
		if (map->size > map->initialCapacity * map->loadFactor) {
			rebuildMyHashMap(map);
		}
	} else {
		re->value = value;
	}
}

//通过key得到数据,如果没有数据则返回null
void* myHashMapGetDataByKey(MyHashMap * const map, void * const key) {
	int hasCode = (*(map->hashCode))(key);
	hasCode %= map->initialCapacity;
	if (hasCode < 0)
		hasCode += map->initialCapacity;
	Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal);
	if (re == NULL) {
		return NULL;
	}
	return re->value;
}

//数据的容量
int myHashMapGetSize(const MyHashMap * const map) {
	return map->size;
}

//创建Entry迭代器
MyHashMapEntryIterator* createMyHashMapEntryIterator(MyHashMap * const map) {
	MyHashMapEntryIterator* re = (MyHashMapEntryIterator*) malloc(
			sizeof(MyHashMapEntryIterator));
	re->count = 0;
	re->index = 0;
	re->map = map;
	re->current = map->entryList[0]->first;
	return re;
}

//释放Entry迭代器
void freeMyHashMapEntryIterator(MyHashMapEntryIterator* iterator) {
	free(iterator);
}

//Entry迭代器是否有下一个
int myHashMapEntryIteratorHasNext(MyHashMapEntryIterator* iterator) {
	return iterator->count < iterator->map->size;
}

//遍历下一个Entry元素
Entry* myHashMapEntryIteratorNext(MyHashMapEntryIterator* iterator) {
	(iterator->count)++;
	while (!(iterator->current)) {
		(iterator->index)++;
		iterator->current = iterator->map->entryList[iterator->index]->first;
	}
	Entry * re = (Entry *) iterator->current->data;
	iterator->current = iterator->current->next;
	return re;
}

//删除一条数据,返回是否删除成功
int myHashMapRemoveDataByKey(MyHashMap * const map, void * const key) {
	int hasCode = (*(map->hashCode))(key);
	hasCode %= map->initialCapacity;
	if (hasCode < 0)
		hasCode += map->initialCapacity;
	MyListIterator* it = createMyListIterator(map->entryList[hasCode]);
	int re = 0;
	while (myListIteratorHasNext(it)) {
		Entry * entry = (Entry *) (myListIteratorNext(it));
		if ((*(map->equal))(entry->key, key)) {
			myListRemoveDataAt(map->entryList[hasCode], it->count - 1);
			re = 1;
			(map->size)--;
			break;
		}
	}
	freeMyListIterator(it);
	return re;
}

void myFree(Entry * p) {
	free(p);
}

//释放HashMap
void freeMyHashMap(MyHashMap * map) {
	myHashMapOutput(map, myFree);
	for (int i = 0; i < map->initialCapacity; i++) {
		freeMyList(map->entryList[i]);
	}
	free(map->entryList);
	free(map);
}

//遍历
void myHashMapOutput(MyHashMap *map, void (*pt)(Entry*)) {
	MyHashMapEntryIterator* iterator = createMyHashMapEntryIterator(map);
	while (myHashMapEntryIteratorHasNext(iterator)) {
		pt(myHashMapEntryIteratorNext(iterator));
	}
	freeMyHashMapEntryIterator(iterator);
}

测试代码如下:


#include <stdio.h>
#include <stdlib.h>
#include "myHashMap.h"

#define S 10

char* strs[S]=
{
    "abc",
    "qq",
    "hello",
    "abc",
    "lmy",
    "ab",
    "qq",
    "lqw",
    "sww",
    "lqw"
};


int hashCode(void *key){
	return (int)key;
}

int equal(void *key1,void *key2){
	return key1 == key2;
}

int main()
{

    int*  data = malloc(sizeof(int)* S);
    for (int i=0; i<S; i++)
    {
        data[i]=i;
    }

    //创建映射需要指定两个函数,hashCode函数和equal函数。
    MyHashMap * map = createMyHashMap(hashCode,equal);

    //插入数据
    for (int i=0; i<S; i++)
    {
        myHashMapPutData(map, strs[i], &data[i]);
    }

    //输出大小
    printf("size=%d\n",myHashMapGetSize(map));

    //测试删除
    myHashMapRemoveDataByKey(map,"qq");
    myHashMapRemoveDataByKey(map,"ab");
    myHashMapRemoveDataByKey(map,"qwert");

    //输出大小
    printf("after remove size=%d\n",myHashMapGetSize(map));

    //遍历
    MyHashMapEntryIterator * it = createMyHashMapEntryIterator(map);
    while(myHashMapEntryIteratorHasNext(it))
    {
        Entry * pp= myHashMapEntryIteratorNext(it);
        char * key = pp-> key;
        int * value = pp->value;
        printf("%s(%d)\n", key, *value);
    }
    //释放遍历器
    freeMyHashMapEntryIterator(it);

    //释放映射
    freeMyHashMap(map);

    //释放数据
    free(data);
    return 0;
}

3、FIFO队列

     FIFO队列基于双向链表实现,同Java LinkedList实现一样,Java中优先使用通过环形数组实现的队列ArrayDeque。

   头文件如下:

#ifndef MYQUEUE_H_INCLUDED
#define MYQUEUE_H_INCLUDED

#include "myList.h"

//数据结构和链表一致
typedef MyList MyQueue;

//创建队列
MyQueue * createMyQueue();

//释放队列
void freeMyQueue(MyQueue * queue);

//插入
void myQueueAdd(MyQueue* const queue, void* const data);

//删除
void* myQueueRemove(MyQueue * const queue);

//取得队头
void* myQueueGetTop(const MyQueue * const queue);

#endif // MYQUEUE_H_INCLUDED

实现如下:

#include "myQueue.h"

//创建队列
MyQueue * createMyQueue()
{
    return createMyList();
}

//释放队列
void freeMyQueue(MyQueue * queue)
{
    freeMyList(queue);
}

//插入
void myQueueAdd(MyQueue* const queue, void* const data)
{
    myListInsertDataAtLast(queue, data);
}

//删除
void* myQueueRemove(MyQueue * const queue)
{
    return myListRemoveDataAtFirst(queue);
}

//取得队头
void* myQueueGetTop(const MyQueue * const queue)
{
    return myListGetDataAtFirst(queue);
}

4、红黑树

     红黑树删除和添加节点时为了保持树的平衡需要考虑各种可能情况做适当的旋转,实现整体比较复杂,参考:

     java8 HashMap数据结构实现源码解析

     java8 TreeMap红黑树节点删除源码解析

      红黑树(二)之 C语言的实现

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用C语言制作一个搜索关键字并能输出关键字所在字段函数,具体步骤如下: 1. 定义函数名和参数。可以定义一个函数名为search_keyword,需要传入三个参数:待搜索的字符串数组(例如,char str[]),字段名称的字符串(例如,char field[]),以及待搜索的关键字(例如,char keyword[])。 2. 遍历待搜索的字符串数组,找到包含字段名称的字符串所在的置,然后将该置后面的字符串进行关键字搜索。 3. 在关键字搜索中,使用strstr函数查找是否包含关键字的子串。如果找到了,可以使用printf函数输出字段名称和关键字所在置,或者将它们存储在另一个数组中。 4. 最后返回搜索结果,可以返回一个整数,表示找到的关键字数量。 下面是一个可能的函数实现代码: ``` int search_keyword(char str[], char field[], char keyword[]) { int found = 0; char *pos; pos = strstr(str, field); while (pos != NULL) { pos += strlen(field); pos = strstr(pos, keyword); if (pos != NULL) { printf("Found keyword '%s' in field '%s'\n", keyword, field); found++; } } return found; } ``` 这个函数使用了while循环和strstr函数,在字符串数组中查找字段名称,然后在该置后面的字符串中查找关键字。如果找到了关键字,将输出它所在的字段名称和置,并且返回找到的关键字数量。 ### 回答2: 使用C语言制作一个搜索关键字并能输出关键字所在字段函数可以按照以下步骤进行: 1. 首先,定义一个结构体,用来表示一个字段。 ```c typedef struct { char fieldName[50]; // 字段名称 char fieldValue[500]; // 字段值 } Field; ``` 2. 然后,定义一个函数来从一系列字段中搜索关键字并输出所在字段。 ```c void searchKeyword(Field fields[], int numFields, char keyword[]) { int i, found = 0; for (i = 0; i < numFields; i++) { if (strstr(fields[i].fieldValue, keyword) != NULL) { printf("关键字 \"%s\" 在字段 \"%s\" 中找到。\n", keyword, fields[i].fieldName); found = 1; } } if (!found) { printf("未找到关键字 \"%s\"。\n", keyword); } } ``` 3. 最后,在主函数中创建一些字段,并调用搜索函数进行测试。 ```c int main() { Field fields[3]; // 假设有3个字段 strcpy(fields[0].fieldName, "标题"); strcpy(fields[0].fieldValue, "搜索引擎"); strcpy(fields[1].fieldName, "作者"); strcpy(fields[1].fieldValue, "John Doe"); strcpy(fields[2].fieldName, "内容"); strcpy(fields[2].fieldValue, "这是一个用C语言编写的搜索函数的例子。"); char keyword[50]; printf("请输入要搜索的关键字: "); scanf("%s", keyword); searchKeyword(fields, 3, keyword); return 0; } ``` 以上代码会输出包含关键字字段,如果没有找到关键字,则会提示未找到。可以根据实际需求进行修改和扩展。 ### 回答3: 在使用C语言制作一个搜索关键字并能输出关键字所在字段函数时,我们可以采用以下步骤: 1. 声明函数:首先,我们需要声明一个函数函数名为searchKeyword。该函数需要传入两个参数:一个是要搜索的关键字,另一个是要搜索的字段(例如一个字符串数组)。函数的返回值可以是一个整数值,表示搜索到的关键字置(索引值)。 2. 字段遍历:在函数内部,我们需要使用循环遍历所给的字段。可以使用for循环来实现遍历,循环的次数为字段的长度。 3. 关键字匹配:针对每个字段,我们需要使用字符串比较函数(例如strcmp)来判断该字段是否包含关键字。如果关键字出现在字段中,strcmp将返回0,否则返回其他值。 4. 输出结果:如果关键字匹配成功(即strcmp返回0),则可以将当前字段置作为返回值返回。否则,继续遍历下一个字段。如果所有字段都遍历完毕但没有找到匹配的关键字,则返回一个特定的标志(例如-1)表示搜索失败。 下面是一个示例代码的简单实现: ``` int searchKeyword(char keyword[], char fields[][50], int numFields) { int i; for (i = 0; i < numFields; i++) { if (strcmp(keyword, fields[i]) == 0) { return i; } } return -1; } ``` 在此示例中,我们传入关键字字段数组作为参数,并使用strcmp函数逐个比较关键字字段。如果匹配成功,则直接返回该字段置(索引值),如果所有字段都遍历完毕但没有找到匹配的关键字,则返回-1表示搜索失败。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值