#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> //基于双向循环链表的例子 #define PDATA void* //#define DEBUG //定义用户结构体数据 /* typedef struct Staff { int id; float wages; }UserData; */ typedef struct Student { int id; char name[20]; char sex[10]; int score; }UserData; //输入信息 void inputInfo(UserData *usrData); void printInfo(UserData usrData); /*-----------双向循环链表结点数据结构---------*/ typedef struct DcllNode { PDATA pdate; //结点数据指针 DcllNode * pre; //指向前个结点的指针 DcllNode * next; //指向后个结点的指针 }*pNode,Node; /*-------------------------------------------*/ /*------------双向循环链表数据结构-----------*/ typedef struct Dcll { pNode virBegin; //虚拟表头指针 pNode virEnd; //虚拟表尾指针 int nodeNum; //结点计数 }*pDcll,Dcll; /*-------------------------------------------*/ /*--------------双向循环链表全局变量---------*/ Dcll dclnkList; /*-------------------------------------------*/ /*--------------双向循环链表操作-------------*/ void DnitDcll(); //初始化双向循环链表 void InsertNode(pNode insNode,pNode usrDatartPos,int shift); //在当前状态位置移位后位置插入结点 pNode DeleteNode(pNode usrDatartPos,int shift); //在当前状态位置移位后位置删除结点 pNode GetNodeP(pNode usrDatartPos,int shift); //得到当前状态位置移位后位置 void DeleteCurNode(pNode curPos); //删除当前指针所指结点 int Delete_if(pNode delnode,void *iffunc); //按条件删除结点 void InsertCurNode(pNode insNode,pNode usrDatartPos); //在当前位置加入结点 int GetNodesNum(); //得到双向循环链表结点个数 void InsertTailNode(pNode insNode); //尾插入结点 void InsertHeadNode(pNode insNode); //头插入结点 void Insert_if(pNode insNode,void *iffunc); //按条件插入数据 int if_function(pNode pnode,pNode); //条件函数 int compare(void * arg1,void * arg2); //比较函数 void printNode(pNode); //输出结点信息 void List(pNode); //输出双向循环链表内容 int isDeleted(pNode pnode,pNode delNode); //删除判定函数 /*------------------------------------------*/ //主函数 int main() { int i; float maxWages = 0; pNode pnode = NULL; for(i = 0; i < 5; ++i) { pnode = (pNode)malloc(sizeof(Node)); pnode->pdate = malloc(sizeof(UserData)); inputInfo((UserData *)(pnode->pdate)); Insert_if(pnode,if_function); #ifdef DEBUG List(dclnkList.virBegin); // printInfo(*(usrData+i)); #endif } // List(dclnkList.virBegin); // printf("输出/n"); pnode = (pNode)malloc(sizeof(Node)); pnode->pdate = malloc(sizeof(UserData)); scanf("%d",&(((UserData *)(pnode->pdate))->score)); strcpy(((UserData *)(pnode->pdate))->name ,"aaa"); strcpy(((UserData *)(pnode->pdate))->sex ,"male"); ((UserData *)(pnode->pdate))->id = 180; if(Delete_if(pnode,isDeleted) == 0) { InsertTailNode(pnode); } List(dclnkList.virBegin); return 0; } void DnitDcll() { dclnkList.nodeNum = 0; //结点数置零 dclnkList.virBegin = dclnkList.virEnd = NULL; //初始虚拟开始结点及虚拟结束结点 } //从当前位置移动shift个位置 pNode GetNodeP(pNode usrDatartPos,int shift = 0) { //没有数据时 if(dclnkList.nodeNum == 0) return NULL; if(shift == 0) return usrDatartPos; int loop; int shfNum = abs(shift); pNode curPos = usrDatartPos; if(shift > 0) //向后移 { for(loop = 0;loop < shfNum; ++loop) { curPos = curPos->next; } return curPos; } else { for(loop = 0;loop < shfNum; ++loop) { curPos = curPos->pre; } return curPos; } } // void InsertCurNode(pNode insNode,pNode usrDatartPos) { //当加入第一个数据时 if(dclnkList.virBegin == NULL) { dclnkList.virBegin = dclnkList.virEnd = insNode; //让其指向自己 insNode->next=insNode; insNode->pre=insNode; ++dclnkList.nodeNum; return; } //更新四个基本的链接 insNode->pre = usrDatartPos; insNode->next = usrDatartPos->next; insNode->next->pre = insNode; usrDatartPos->next = insNode; //对虚拟链首及链尾的更新 if(usrDatartPos == dclnkList.virEnd) { dclnkList.virEnd = usrDatartPos->next; } //更新结点个数 ++dclnkList.nodeNum; } //删除当前结点 void DeleteCurNode(pNode curPos) { //如果当前只有一个结点 if(dclnkList.nodeNum == 1) { dclnkList.virBegin = dclnkList.virEnd = NULL; --dclnkList.nodeNum; //释放当前待删除结点所占空间 free(curPos->pdate); free(curPos); return ; } curPos->next->pre = curPos->pre; curPos->pre->next = curPos->next; --dclnkList.nodeNum; //更新链首、链尾 if(curPos == dclnkList.virBegin) { dclnkList.virBegin = curPos->next; } if(curPos == dclnkList.virEnd) { dclnkList.virEnd = curPos->pre; } //释放当前待删除结点所占空间 free(curPos->pdate); free(curPos); } void InsertNode(pNode insNode,pNode usrDatartPos,int shift) { InsertCurNode(insNode,GetNodeP(usrDatartPos,shift)); } pNode DeleteNode(pNode usrDatartPos,int shift = 0) { pNode pnode = GetNodeP(usrDatartPos,shift); DeleteCurNode(pnode); return pnode; } int GetNodesNum() { return dclnkList.nodeNum; } void InsertTailNode(pNode insNode) { InsertCurNode(insNode,dclnkList.virEnd); //dclnkList.virEnd = dclnkList.virEnd->next; } void InsertHeadNode(pNode insNode) { InsertTailNode(insNode); dclnkList.virBegin = dclnkList.virEnd; //此时已更新了虚拟结束节点,要重设结束节点 dclnkList.virEnd = dclnkList.virEnd->pre; } int if_function(pNode pnode1,pNode pnode2) { // printf("执行判断/n"); if(pnode2 == NULL) return 1; return compare(pnode1->pdate,pnode2->pdate); } void Insert_if(pNode insNode,void *iffunc) { if(dclnkList.nodeNum == 0) { InsertHeadNode(insNode); return; } if(if_function(insNode,dclnkList.virBegin)) { #ifdef DEBUG printf("加在beginnode 前/n"); #endif InsertHeadNode(insNode); return; } if(!if_function(insNode,dclnkList.virEnd)) { #ifdef DEBUG printf("加在endnode后/n"); #endif InsertTailNode(insNode); return; } pNode curP = dclnkList.virBegin->next; // int condition = ((*(void (*)(pNode,pNode))iffunc)(insNode,curP)); int condition = (*((int (*)(pNode,pNode))(iffunc)))(insNode,curP); int i = 0; while(i < dclnkList.nodeNum && !condition) { curP = curP->next; condition = (*((int (*)(pNode,pNode))(iffunc)))(insNode,curP); ++i; } InsertCurNode(insNode,curP->pre); } int Delete_if(pNode delnode,void *iffunc) { pNode pnode = dclnkList.virBegin; pNode tmp; int count = 0;//用于计数 int i; for(i = 0 ;i < dclnkList.nodeNum ; ++i) { if( (*(int(*)(pNode,pNode))(iffunc))(delnode,pnode) ) { count++; tmp = pnode->next; DeleteCurNode(pnode); pnode = tmp; continue; } pnode = pnode->next; } return count; } void List(pNode pnode) { pNode tmp = pnode; int i; #ifdef DEBUG printf("共%d个结点/n",dclnkList.nodeNum); #endif for(i = 0;i < dclnkList.nodeNum; ++i) { #ifdef DEBUG printf("第%d个结点/n",i+1); #endif printNode(tmp); tmp = tmp->next; } } void printNode(pNode pnode) { printInfo(*((UserData *)(pnode->pdate))); } /*-----------------用户函数-----------------*/ int compare(void * arg1,void * arg2) { if(arg2 == NULL) return 0; UserData * usrData1 = (UserData *)arg1; UserData * usrData2 = (UserData *)arg2; if(usrData1->id <= usrData2->id) return 1; return 0; } int isDeleted(pNode pnode,pNode delNode) { if( ((UserData *)(pnode->pdate))->score == ((UserData *)(delNode->pdate))->score ) { return 1; } return 0; } void inputInfo(UserData *usrData) { // scanf("%d%f",&usrData->id,&usrData->wages); scanf("%d",&usrData->id); scanf("%s",&usrData->name); scanf("%s",&usrData->sex); scanf("%d",&usrData->score); getchar(); } void printInfo(UserData usrData) { //printf("%d/n%.2f/n",usrData.id,usrData.wages); printf("%d/n%s/n%s/n%d/n",usrData.id,usrData.name,usrData.sex,usrData.score); 一个双向循环链表的小例子,包含了链表的大部分操作。有一定的通用性,足能应付链表操作。 用到了一些 void *指针,及函数指针。包含大量的指针相互转化。仅供参考。