通用鏈表
通用鏈表與一般鏈表不同的地方在與其數據域類型是不確定的,我們用void這個萬能指針來代替原有的數據域類型
void是一個萬能指針,可以與任意類型的指針互換,如 int* = void*,char* =void*
要注意的一點是:由於存儲類型的不確定性,我們無法直接使用到關係運算符進行運算,需要使用者提供一個函數供鏈表使用,也就是回調函數
比方說比較兩個數據時,我們不知道數據類型,就要自己提供一個比較函數。
通用鏈表的創建
準備工具
就之前而言,通用鏈表的難點就是我們無法使用關係運算符,如相等,不等等,所以我們需要先準備一個比較函數
int cmp(const void*ptr1,const void*ptr2)
{
const double* p1=ptr1;
//這裏只是舉例爲double類型,根據實際需要可以自己改變類型
//比如說學生管理系統裏,節點爲Student*類型,那我們就可以改爲
//const Student* 然後再比較需要比較的數據類型
const double* p2=ptr2;
if(*p1>*p2)
return 1;
else if(*p1<*p2)
return -1;
else
return 0;
}
如果我們需要顯示節點中的數據,由於不知道數據類型,我們也要自己寫一個函數
void show(void* ptr)
{
const double* p=ptr;//同理如上,double只是舉例
printf("%lf",p);
}
創建結點
與普通鏈表相比,只是改變了數據域的類型
typedef struct Node
{
void* ptr; //從準確的數據類型變爲指向首地址的指針,那麼數據類型我們就可以進行改變
struct Node* next;
}Node;
Node* creat_node(void* ptr)
{
Node* node=malloc(sizeof(Node));
node->ptr=ptr;
node->next= NULL;
return node;
}
創建鏈表
typedef struct List
{
Node* head;
size_t size;
}List;
List* creat_list(void)
{
List* list = malloc(sizeof(List));
list->head=NULL;
list->size=0;
return list;
}
對鏈表的操作
大部分操作與鏈表相同,我就寫一些稍微不同的
查找值爲value的元素
int find_list(List* list,void* ptr,compar cmp)
{
int index=0;
for(Node* i=list->head;NULL != i;i=i->next)
{
if(0 == cmp(i->ptr,ptr))//調用上述函數進行比較
{
return index;
}
index++;
}
}
遍歷
void show_list(List* list,void(*show)(const void* ptr))
{
for(Node* i=list->head;NULL != i;i=i->next)
{
show(i->ptr);
}
printf("\n");
}
其餘的與長長鏈表差不多相同,稍微修改下參數就行了,需要比較的話參考查找就行