数据结构 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<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#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<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#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<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdbool.h>

typedef 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<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#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;i<pos&& temp->next !=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;i<pos&&temp->next!=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<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#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.o
	gcc -g -o node main.o day03.o student.o
main.o:main.c
	gcc -g -c  main.c -o main.o
day03.o:day03.c
	gcc -g -c day03.c -o day03.o
student.o:student.c
	gcc -g -c student.c -o student.o 
	

4.多加  复习(读懂 函数指针)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值