数据结构与算法:单链表(利用万能指针实现对任意类型数据进行操作)
生活随笔
收集整理的這篇文章主要介紹了
数据结构与算法:单链表(利用万能指针实现对任意类型数据进行操作)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
C語言的指針真的很強大,萬能指針更強大,可以指向任意類型的數據。在上篇博客?數據結構與算法:單鏈表(超詳細實現)中用C語言實現了單鏈表的相關算法,不過卻有局限性 只能針對某一種數據類型還是不夠強大。C語言中沒有C++中的模板 那如何來實現 類似模板的效果呢?可以針對任意類型數據的單鏈表呢?在C語言中就有這么一種類型 可以指向任意數據類型的指針,它就是萬能指針 void* ,就是它 ,可以利用它實現 類似模板的效果!我們在鏈表中不維護數據,我們只維護數據的地址,那么我們的void* 就可保存任意類型的地址!
實現算法預覽
LinkList.h
#pragma once #ifndef __LINKLIST_H__ #define __LINKLIST_H__typedef struct LinkNode LinkNode; struct LinkNode {void* data;//維護用戶提供的數據LinkNode* next; }; typedef struct LINKLIST {LinkNode *pHeader;int m_size; }LINKLIST;typedef void* LinkList;//對外提供void*防止用戶看到不該看到的東西,避免用戶亂修改//初始化單鏈表 LinkList Init_LinkList();//根據位置插入元素 //pos 位置范圍為1 ~ list->size 更符合人類的叫法 int InsertByIndex_LinkList(void* list, int pos, void* data);//插入元素根據元素值 int InsertByValue_LinkList(void* list, void* search,void* data,int(*compareFunction)(void* data1, void* data2));//刪除元素根據位置 int RemoveByIndex_LinkList(void* list, int pos);//刪除元素根據值 int RemoveByValue_LinkList(void * list, void * data, int(*compareFunction)(void* data1, void* data2));//清空鏈表 int Clear_LinkList(void* list);//銷毀鏈表 int Destroy_LinkList(void* list);//獲取鏈表元素個數 int Length_LinkList(void* list);//遍歷鏈表 int Foreach_LinkList(void* list, void(*foreachFunction)(void* data));//翻轉鏈表 int Reverse_LinkList(void* list);#endif // !__LINKLIST_H__
實現代碼展示
LinkList.c
#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include "LinkList.h"LinkList Init_LinkList() {LINKLIST* list = (LINKLIST*)malloc(sizeof(LINKLIST));list->pHeader = (LinkNode*)malloc(sizeof(LinkNode));list->pHeader->data = NULL;list->pHeader->next = NULL;list->m_size = 0;return list; } //根據位置插入元素 //pos 位置范圍為1 ~ list->size int InsertByIndex_LinkList(void* list, int pos, void* data) {LINKLIST* linkList = (LINKLIST*)list;//非法情況if (NULL == list || NULL == data){return 0;}//位置非法 進行尾插if (pos<1 || pos>=linkList->m_size + 1){pos = linkList->m_size + 1;}LinkNode* pre = linkList->pHeader;//找到 第pos位置前面一個元素for (int i = 1; i < pos; i++){pre = pre->next;}//創建結點LinkNode* newNode = (LinkNode*)malloc(sizeof(LinkNode));newNode->data = data;newNode->next = pre->next;pre->next = newNode;linkList->m_size++;return 1; } int InsertByValue_LinkList(void* list, void* search,void* data, int(*compareFunction)(void* data1, void* data2)) {if (NULL == list || NULL == search || data == NULL || NULL == compareFunction){return 0;}LINKLIST* linkList = (LINKLIST*)list;LinkNode* pre = linkList->pHeader;LinkNode* cur = linkList->pHeader->next;LinkNode* insertPre = NULL;for (int i = 0; i < linkList->m_size; i++){if (compareFunction(cur->data, search)){insertPre = pre;break;}pre = cur;cur = cur->next;}//如果沒有找到要插入的位置 將其插在尾結點LinkNode* newNode = (LinkNode*)malloc(sizeof(LinkNode));newNode->data = data;newNode->next = cur;pre->next = newNode;linkList->m_size++;return 1; } int RemoveByIndex_LinkList(void * list, int pos) {if (NULL == list){return 0;}LINKLIST* linkList = (LINKLIST*)list;//位置非法返回if (pos > linkList->m_size || pos < 1){return 0;}LinkNode* cur = linkList->pHeader;//找到刪除元素的前驅結點for (int i = 1; i < pos; i++){cur = cur->next;}//緩存待刪除結點LinkNode* del = cur->next;//前驅結點指向刪除結點后繼結點cur->next = del->next;//刪除結點free(del);linkList->m_size--;return 1; } int RemoveByValue_LinkList(void * list, void * data,int (*compareFunction)(void* data1,void* data2)) {if (NULL == list || NULL == data || NULL == compareFunction){return 0;}LINKLIST* linkList = (LINKLIST*)list;LinkNode* pre = linkList->pHeader;LinkNode* cur = linkList->pHeader->next;LinkNode* delPre = NULL;for (int i = 0; i < linkList->m_size; i++){if (compareFunction(cur->data,data)){delPre = pre;break;}pre = cur;cur = cur->next;}if (NULL != delPre && NULL != cur){//刪除元素前驅結點指向刪除元素的后繼結點delPre->next = cur->next;//刪除結點free(cur);cur = NULL;}linkList->m_size--;return 1; } int Clear_LinkList(void * list) {if (NULL == list){return 0;}LINKLIST *linkList = (LINKLIST*)list;LinkNode* cur = linkList->pHeader->next;for (int i = 0; i < linkList->m_size; i++){LinkNode* next = cur->next;free(cur);cur = next;}linkList->m_size = 0;return 1; } int Destroy_LinkList(void * list) {if (NULL == list){return 0;}LINKLIST* linkList = (LINKLIST*)list;Clear_LinkList(linkList);free(linkList->pHeader);linkList->pHeader = NULL;return 1; } int Length_LinkList(void * list) {if (NULL == list){return -1;}LINKLIST* linkList = (LINKLIST*)list;return linkList->m_size; } int Foreach_LinkList(void* list, void(*foreachFunction)(void* data)) {if (NULL == list || NULL == foreachFunction){return 0;}LINKLIST* linkList = (LINKLIST*)list;LinkNode* cur = linkList->pHeader->next;for (int i = 0; i < linkList->m_size; i++){foreachFunction(cur->data);cur = cur->next;}return 1; }int Reverse_LinkList(void * list) {if (NULL == list){return 0;}LINKLIST* linkList = (LINKLIST*)list;LinkNode* pre = NULL;LinkNode* cur = linkList->pHeader->next;LinkNode* next = NULL;while (cur!=NULL){//記錄下一個結點next = cur->next;//當前結點指向前驅結點cur->next = pre;//cur pre 往后移動pre = cur;cur = next;}//將頭結點指向最后一個結點 實現翻轉linkList->pHeader->next = pre;return 1; }
Main.c
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LinkList.h"//使用結構體數據類型 測試萬能單鏈表 typedef struct Hero {char name[64];int age; }Hero;int Compare_Hero(void* hero1, void* hero2) {Hero* h1 = (Hero*)hero1;Hero* h2 = (Hero*)hero2;return h1->age == h2->age && strcmp(h1->name, h2->name) == 0; } void Print_Hero(Hero* hero) {if (NULL == hero){return;}printf("name:%s,age:%d\n", hero->name, hero->age);return; } int main(int argc, char *argv[]) {Hero h1 = { "關羽",38 };Hero h2 = { "張飛",39 };Hero h3 = { "趙云",29 };Hero h4 = { "許褚",19 };Hero h5 = { "魯肅",25 };Hero h6 = { "周瑜",27 };Hero h7 = { "太史慈",40 };LinkList list = Init_LinkList();//根據位置進行插入InsertByIndex_LinkList(list, 1, &h1);InsertByIndex_LinkList(list, 100, &h2);InsertByIndex_LinkList(list, 1, &h3);InsertByIndex_LinkList(list, 2, &h4);InsertByIndex_LinkList(list, 3, &h5);InsertByIndex_LinkList(list, 1, &h6);//根據值進行插入InsertByValue_LinkList(list, &h5, &h7, Compare_Hero);//將太史慈插入到魯肅之前printf("元素個數:%d\n", Length_LinkList(list));//正確順序 周瑜 趙云 許褚 太史慈 魯肅 關羽 張飛 Foreach_LinkList(list, Print_Hero);//刪除第一個元素 周瑜RemoveByIndex_LinkList(list, 1);//刪除位置非法RemoveByIndex_LinkList(list, 100);//根據值進行刪除Hero hero = { "許褚",19 };RemoveByValue_LinkList(list, &hero,Compare_Hero);printf("元素個數:%d\n", Length_LinkList(list));//正確順序 趙云 太史慈 魯肅 關羽 張飛 Foreach_LinkList(list, Print_Hero);printf("翻轉后:\n");//翻轉Reverse_LinkList(list);Foreach_LinkList(list, Print_Hero);//清空鏈表Clear_LinkList(list);printf("清空鏈表后,元素個數:%d\n", Length_LinkList(list));//銷毀鏈表Destroy_LinkList(list);return 0; }
運行結果檢測
總結
以上是生活随笔為你收集整理的数据结构与算法:单链表(利用万能指针实现对任意类型数据进行操作)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mysql 学习笔记08
- 下一篇: 数据结构与算法系列——排序(3)_折半插