数据结构 day04 基础知识学习 (接着昨天的讲)
一.知识点主要是在代码里,知识点有:循环链表,函数的接口调用, viod* 类型的函数的运用
和循环列表的增删改查 (这里有点难,主要是老师让我们假装不知链表的存储的数据类型,还有就是要我们使用函数指针来 调用函数,,一言难尽 (bug 太多了,还好在老师的帮助下修好了))
二.有6个文件
1.student.h
2.student.c
3.day03.h
4.day03.c
5.main.c
6.makefile
三.代码:
1.student.h
#ifndef __STUDENT_H__
#define __STUDENT_H__
#include
#include
#include
#include
#include
#include
#include"day03.h"typedef struct student
{char name[100];int m_id;int m_age;char sex;
}stu,*pstu;int pcmp_name(const void *x,const void *y);
int pcmp_id(const void *x,const void* y);
void student_show(const void *ptr);
void student_updata_sex1(void *data1,const void* data2);
#endif
2.student.c
/*************************************************************************************************************************************************************************************************************************文件名:student.c*作 者:She001*时 间:*版 本:*作 用:学生的函数
****************************************************************************************************************************************************************************************************************************/
#include
#include
#include
#include
#include
#include
#include "student.h"
#include "day03.h"void student_updata_sex1(void* data1,const void * data2) //修改学生信息中的性别 (函数指针调用)
{pstu ptem1= (pstu)data1;const pstu ptem2 = (const pstu) data2;ptem1->sex=ptem2->sex; //函数的直接赋值
}
int pcmp_name(const void *x,const void *y) //比较学生的姓名是否相同(函数指针调用)
{if((x==NULL) || (y==NULL)){return -1;}//printf("1:%s \t 2:%s \n",((stu*)(x))->name,((stu*)(y))->name);pstu name1 =(pstu)x;pstu name2 =(pstu)y;//printf("1:%s \t 2:%s \n",name1->name,name2->name);return strcmp(name1->name,name2->name);
}int pcmp_id(const void *x,const void* y) //比较学生的id 是否相同(函数指针调用)
{if((x=NULL) || (y=NULL)){return -1;}pstu name1 =(pstu)x;pstu name2 =(pstu)y;return name1->m_id - name2->m_id;}void student_show(const void *ptr) //显示函数(函数指针调用)
{if(ptr==NULL){return;}pstu student1 =(pstu) ptr;printf("姓名:%s\t id:%d\t 年龄:%d\t 性别:%c\n",student1->name,student1->m_id,student1->m_age,student1->sex);}
day03.h
#ifndef __DAY03_H__
#define __DAY03_H__
#include
#include
#include
#includetypedef struct node
{void * data; //数据域struct node* next; //指针域 ,指向下一个节点struct node* prev; //指针域 ,指向上一个节点
}node_t,*pnode_t;enum node_insert_error //共用体 为了模仿报错返回的值
{node_insert_error0 = 0, //没错误node_insert_error1 = 1, //链表的首地址传入错误node_insert_error2 = 2, //链表的数据节点指针错误node_insert_error3 = 3, //传入的位置错误node_insert_error4 = 4, //节点申请失败
};node_t* create_head_node(); //创建头节点的空间节点
node_t* create_node(); //创建空间节点
int node_insert_end(node_t *head ,void *data ,int size);//尾部添加节点
int node_insert_head(node_t *head ,void *data ,int size);//头部添加节点
void delete_node_head(node_t * head); //删除头部节点
void delete_node_end(node_t * head); //删除尾部节点
int insert_pos_node(node_t *head,int pos,void *data,int size);//在固定的位置增加节点
void node_update(node_t * ptr,const void *data_updata,void (*pUpdate)(void *a,const void *b )); //函数接口
void delete_pos_node(node_t* head,int pos);//在固定的位置删除节点
void delete_some_node(node_t *head);删除除了头节点之外的所有节点
bool isEmpty(node_t *head); ///判断指针是否为空
void node_show(node_t* head,void(*pshow)(const void* ptr )); //输出函数 (函数接口)
node_t* node_find(node_t *head ,void * data_par , int (*pcmp)(const void * x,const void *y)); //判断查询函数 (函数接口)
void node_delete(node_t *head ,void * data_par , int (*pcmp)(const void * x,const void *y)); //删除函数 (函数接口)#endif
day03.c
/*************************************************************************************************************************************************************************************************************************文件名:day03.c*作 者:She001*时 间:*版 本:*作 用:双向链表的建立
****************************************************************************************************************************************************************************************************************************/
#include
#include
#include
#include
#include
#include
#include "day03.h"
#include "student.h"/**************************** 函数名:create_head_node* 参数:无* * * 返回值: node_t *s* 作用:创建头节点的空间节点(x循环列表)* *************************/
node_t* create_head_node()//创建头节点的空间节点
{ node_t* head = (node_t *)malloc(sizeof(node_t));if(NULL==head){printf("头节点申请错误!\n");return NULL;}head->data =NULL;head->next=head;head->prev=head;return head;
}/**************************** 函数名:create_node* 参数:无* * * 返回值: node_t *s* 作用:创建的空间节点* *************************/
node_t* create_node() //创建空间节点
{node_t* gw = (node_t *)malloc(sizeof(node_t));if(NULL==gw){printf("空间申请错误!\n");return NULL;}gw->data=NULL;gw->next=NULL;gw->prev=NULL;return gw;
}/**************************** 函数名:node_insert_end* 参数:node_t *head //头节点* void *data //数据* int size //数据大小* * * 返回值: int 类型* 作用:尾部加入节点(x循环列表)* *************************/
int node_insert_end(node_t *head ,void *data ,int size)//尾部添加节点
{if(NULL ==head){printf("首地址错误\n");return node_insert_error0; //首地址错误}if(NULL==data){printf("数据指针错误!\n");return node_insert_error2; //数据指针错误}//申请一个新的节点node_t* gg=create_node();if(NULL==gg){printf("申请空间的节点失败!\n");return node_insert_error4;}gg->data=malloc(size);if(NULL==gg->data){printf("申请空间的节点失败!\n");return node_insert_error4;}memcpy(gg->data,data,size);head->prev->next=gg;gg->prev=head->prev;head->prev=gg;gg->next=head;return node_insert_error0;}/**************************** 函数名:node_insert_end* 参数:node_t *head //头节点* void *data //数据* int size //数据大小* * * 返回值: int 类型* 作用:头部插入空间节点(x循环列表)* *************************/int node_insert_head(node_t *head ,void *data ,int size)//头部添加节点
{if(NULL ==head){printf("首地址错误\n");return node_insert_error0; //首地址错误}if(NULL==data){printf("数据指针错误!\n");return node_insert_error2; //数据指针错误}//申请一个新的节点node_t* gg=create_node();if(NULL==gg){printf("申请空间的节点失败!\n");return node_insert_error4;}gg->data=malloc(size);if(NULL==gg->data){printf("申请空间的节点失败!\n");return node_insert_error4;}memcpy(gg->data,data,size); gg->next=head->next;head->next->prev=gg;head->next=gg;gg->prev=head;
}/**************************** 函数名:isEmpty* 参数:node_t *head //头节点* * 返回值: 无* 作用:判断链表是否为空* *************************/
bool isEmpty(node_t *head)
{if(head==NULL){return true;}else if(head->next==head){return true;}else{return false;}
} /**************************** 函数名:delete_node_end* 参数:node_t *head //头节点* * 返回值: 无* 作用:删除尾部的空间节点(x循环列表)* *************************/
void delete_node_end(node_t * head) //删除尾部节点
{if(isEmpty(head)){printf("数据为空!\n");return;}if(NULL ==head){printf("首地址错误\n");printf("已经是空的!");//return node_insert_error1; //首地址错误return;}if((head->prev)==NULL){printf("链表已经为空!\n");//return node_insert_error1;return;} node_t *p = head->prev;head->prev=head->prev->prev;head->prev->next=head;if(p->data!=NULL){free(p->data);}printf("删除成功!\n");free(p);p=NULL;
}/**************************** 函数名:node_insert_head* 参数:node_t *head //头节点* * 返回值: void* 作用:删除头部的空间节点(x循环列表)* *************************/
void delete_node_head(node_t * head) //删除头部节点
{if(isEmpty){return;}if(NULL ==head){printf("首地址错误\n");printf("已经是空的!");//return node_insert_error1; //首地址错误return ;}if((head->next)==NULL){printf("链表已经为空!\n");//return node_insert_error1;return;} node_t *p = head->next;head->next=p->next;p->next->prev=head;if(p->data!=NULL){free(p->data);}free(p);p=NULL;
}/**************************** 函数名:delete_some_node* 参数:node_t *head //头节点* * 返回值: void* 作用:删除除了头部的所有空间节点(x循环列表)* *************************/
void delete_some_node(node_t *head)
{if(isEmpty){return;}while(head->next!=head){delete_node_head(head); }
}/**************************** 函数名:delete_pos_node* 参数:node_t *head //头节点* * 返回值: void* 作用:删除固定位置的空间节点(x循环列表)* *************************/
void delete_pos_node(node_t* head,int pos)
{ if(isEmpty){return;}node_t* temp= head;int i=0;for(i=0;inext !=head;++i){ temp=temp->next;}if(i==pos){temp->prev->next=temp->next;temp->next->prev=temp->prev;if(temp->data!=NULL){free(temp->data);}free(temp);temp=NULL;}
}
/*********************** 作用: 对某个数据更新* 参数: ptr 需要修改数据的首地址* data_updata 需要更新数据的指针* pUpdate 函数指针* * *******************/
void node_update(node_t * ptr,const void *data_updata,void (*pUpdate)(void *a,const void *b ))
{if(ptr==NULL || data_updata ==NULL || pUpdate==NULL){return ; }pUpdate(ptr->data,data_updata);
}/**************************** 函数名:node_insert_end* 参数:node_t *head //头节点* void *data //数据* int size //数据大小* int pos //数据的位置* * 返回值: int 类型* 作用:插入固定的空间节点(x循环列表)* *************************/int insert_pos_node(node_t *head,int pos,void *data,int size)
{if(NULL ==head){printf("首地址错误\n");return node_insert_error0; //首地址错误}if(NULL==data){printf("数据指针错误!\n");return node_insert_error2; //数据指针错误}//申请一个新的节点node_t* gg=create_node();if(NULL==gg){printf("申请空间的节点失败!\n");return node_insert_error4;}gg->data=malloc(size);if(NULL==gg->data){printf("申请空间的节点失败!\n");return node_insert_error4;}memcpy(gg->data,data,size);int i=0; node_t *temp =head; for(i=0;inext!=head;i++){temp=temp->next;}if(i==pos){gg->prev=temp->prev;temp->prev->next=gg;gg->next=temp;temp->prev=gg;}
}/**************************** 函数名:node_show* 参数:node_t *head //头节点* pshow 函数指针* * 返回值: 无* 作用: 打印链表所有的内容* *************************/
void node_show(node_t* head,void(*pshow)(const void* ptr ))
{if(head ==NULL || pshow ==NULL){printf("参数错误,传入的指针为空!\n");return;}node_t * temp = head->next;while(temp->data!=NULL){pshow(temp->data);temp=temp->next;}
}/**************************** 函数名:node_find* 参数:node_t *head //头节点* data_par 需要查找的指针数据* pcmp 函数指针* 返回值: int* 作用: 在循环列表找data_par 的数据* *************************/
node_t* node_find(node_t *head ,void * data_par , int (*pcmp)(const void * x,const void *y))
{if(head==NULL || data_par==NULL || pcmp ==NULL){printf("指针错误!\n");return NULL;}node_t* temp =head->next;printf("0000000000000000000000000000000000000000\n");while(temp->data!=NULL){printf("h1:%s\n",((stu*)(temp->data))->name);printf("h2:%s\n",((stu*)(data_par))->name);if(pcmp(temp->data,data_par)==0){return temp; }temp=temp->next;printf("-=-=-=-=-=-=-=\n");}printf("1111111111111111111111111111111111111111111\n");return NULL;
}/**************************** 函数名:node_delete* 参数:node_t *head //头节点* data_par 需要查找的指针数据* pcmp 函数指针* 返回值: void* 作用: 在循环列表找data_par 并且删除他的数据* *************************/
void node_delete(node_t *head ,void * data_par , int (*pcmp)(const void * x,const void *y))
{if(head==NULL || data_par==NULL || pcmp ==NULL){printf("指针错误!\n");return ;}node_t* temp =head ->next;while(temp->data!=NULL){if(pcmp(data_par,temp->data)==0){temp->prev->next=temp->next;temp->next->prev=temp->prev;return ; }temp=temp->next;}
}
main.c
/*************************************************************************************************************************************************************************************************************************文件名:main.c*作 者:She001*时 间:*版 本:*作 用:程序接口
****************************************************************************************************************************************************************************************************************************/
#include
#include
#include
#include
#include
#include
#include "student.h"
#include "day03.h"int main()
{int i;/*typedef struct student{char name[100];int m_id;int m_age;char sex;}stu,*pstu;*/stu w={"123",1,1,'0'};stu w1={"1234",12,12,'1'};stu w2={"12345",13,13,'2'};stu w3={"123456",14,14,'3'};stu w4={"1234567",15,15,'4'};stu w5={"12345678",16,16,'5'};node_t* head=create_head_node(); node_insert_head(head ,&w ,sizeof(stu));node_insert_head(head ,&w1 ,sizeof(stu));node_insert_head(head ,&w2 ,sizeof(stu));node_insert_head(head ,&w3 ,sizeof(stu));node_insert_head(head ,&w4 ,sizeof(stu));node_insert_head(head ,&w5 ,sizeof(stu));node_show(head,student_show);printf("-----------------------------------\n");delete_node_end(head);node_show(head,student_show); printf("++++++++++++++++++++++++++++++++++++\n"); node_t* temp=head;for(i=0;temp->next!=head;i++){temp=temp->next;printf("第%d个学生:\n",i+1);printf("name:%s \n",((stu*)(temp->data))->name);printf("id:%d\n",((stu*)(temp->data))->m_id); //temp->data 是一个 void * 因为id 是stu 类型的 所以我们需要一个 stu* 类型的指针来指向printf("age: %d\n",((stu*)(temp->data))->m_age);printf("sex: %c\n\n",((stu*)(temp->data))->sex);}printf("55555555555555555555555555555555555555555555\n");node_t * pt =node_find(head,&w3,pcmp_name);if(pt==NULL){printf("没有找到!\n");}node_update(pt,&w2,student_updata_sex1);printf("===============================\n");node_show(head,student_show);/*node_t* temp=head;for(i=0;temp->next!=head;i++){temp=temp->next;printf("第%d个学生:\n",i+1);printf("name:%s \n",((stu*)(temp->data))->name);printf("id:%d\n",((stu*)(temp->data))->m_id); //temp->data 是一个 void * 因为id 是stu 类型的 所以我们需要一个 stu* 类型的指针来指向printf("age: %d\n",((stu*)(temp->data))->m_age);printf("sex: %c\n\n",((stu*)(temp->data))->sex);}temp=head->next->next;node_update(temp,&w,student_updata_sex1);printf("==========================================================================\n");temp=head;for(i=0;temp->next!=head;i++){temp=temp->next;printf("第%d个学生:\n",i+1);printf("name:%s \n",((stu*)(temp->data))->name);printf("id:%d\n",((stu*)(temp->data))->m_id); //temp->data 是一个 void * 因为id 是stu 类型的 所以我们需要一个 stu* 类型的指针来指向printf("age: %d\n",((stu*)(temp->data))->m_age);printf("sex: %c\n\n",((stu*)(temp->data))->sex);}
*/
}
makefile
node : main.o day03.o student.ogcc -g -o node main.o day03.o student.o
main.o:main.cgcc -g -c main.c -o main.o
day03.o:day03.cgcc -g -c day03.c -o day03.o
student.o:student.cgcc -g -c student.c -o student.o
4.多加 复习(读懂 函数指针)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
