zl程序教程

您现在的位置是:首页 >  其他

当前栏目

数据结构模版----单链表SimpleLinkList[带头结点&&面向对象设计思想](C语言实现)

ampC语言数据结构 实现 设计 ---- 面向对象 思想
2023-09-14 08:59:42 时间
    ElemType            m_data;         // 数据域       struct LinkListNode *m_next;            // 指针域   }LinkListNode;   // 带头结点的单项链表   typedef struct LinkList       LinkListNode    *m_head;                // 链表头结点       int             m_length;           // 单链表数据结点个数指针域   }LinkList;   ///*////////////////////////////////////////////////////////////////////////////   ///   /// 创建和初始化单链表   ///   /// 创建      LinkList* CreatLinkList(void)   /// 初始化 void InitLinkList(LinkList *list)   ///*////////////////////////////////////////////////////////////////////////////   LinkList* CreatLinkList(void)      list    :   指向一个链表指针,此处传入表头地址      若成功返回创建好的单链表的指针      开辟一个单链表数据结构,并初始化头结点,然后将创建好的单链表指针返回      使用CreateLinkList创建的单链表,需要用DestroyLinkList来销毁      以免发生内存泄漏  LinkList* CreateLinkList(void)       LinkList *list = NULL;       if((list = (LinkList *)malloc(sizeof(LinkList))) == NULL)       // 开辟单链表的空间       {   // 开辟失败           fprintf(stderr, "not enough memory when CREATE LIST...\n");           exit(EXIT_FAILURE);       }       InitLinkList(list);             // 初始化单链表       return list;   void InitLinkList(LinkList *list)      list    :   指向一个链表指针,此处传入表头地址      无      初始化单链表, 执行以下操作      ①开辟头结点的空间 ②进行必要的初始化[头结点的初始化和单链表结点数目的初始化]      使用InitLinkList初始化的单链表(初始化时malloc了头结点m_head的空间)      而使用用FinitLinkList来进行后处理(后处理时free了头结点的m_head空间)      以免发生内存泄漏  void InitLinkList(LinkList *list)       if((list- m_head = malloc(sizeof(LinkListNode))) == NULL)        // 为头结点开辟空间       {   // 开辟失败           fprintf(stderr, "not enough memory when MALLOC HEAD...");           exit(EXIT_FAILURE);       }       list- m_head- m_next = NULL;          // 初始化只有头结点       list- m_head- m_data = 0;             // 数据元素个数为0       list- m_length = 0;                      // 数据元素个数为0   ///*////////////////////////////////////////////////////////////////////////////   ///   /// 销毁以及后处理单链表   ///   /// 销毁用CreateLinkList创建的单链表   /// void DestroyLinkList(LinkList *list)   ///   /// 后处理单链表,   /// void FinitLinkList(LinkList *list)   ///   /// 清空单链表中的所有元素   /// void ClearLinkList(LinkList *list)   ///*////////////////////////////////////////////////////////////////////////////   void DestroyLinkList(LinkList *list)      list    :   指向一个链表指针,此处传入表头地址      无      销毁用CreateLinkList创建的单链表,执行以下操作      ①清空单链表  ②释放头结点  ③释放单链表      使用CreateLinkList创建的单链表,需要用DestroyLinkList来销毁      以免发生内存泄漏  LinkList* DestroyLinkList(LinkList *list)       ClearLinkList(list);            // 清空链表       FinitLinkList(list);            // 销毁头结点       if(list != NULL)                // 销毁链表的空间       {           free(list);           list = NULL;       }   void FinitLinkList(LinkList *list)      list    :   指向一个链表指针,此处传入表头地址      无      后处理单链表, 执行以下操作      ①开辟头结点的空间 ②进行必要的初始化[头结点的初始化和单链表结点数目的初始化]      使用InitLinkList初始化的单链表(初始化时malloc了头结点m_head的空间)      而使用用FinitLinkList来进行后处理(后处理时free了头结点的m_head空间)      以免发生内存泄漏  void FinitLinkList(LinkList *list)       assert(list- m_head- m_next == NULL);     // 后处理指针针对空链表       // assert(list- m_length == 0);       if(list- m_head != NULL)         // 如果此时头结点空间未被销毁       {           free(list- m_head);           list- m_head = NULL;           list- m_length = -1;         // 未经初始化的单链表元素个数记为-1       }   void ClearLinkList(LinkList *list)      list    :   指向一个链表指针,此处传入表头地址      无      清空单链表中的所有元素  void ClearLinkList(LinkList *list)       while(list- m_head- m_next != NULL)       {           DeleteNode(list, 0);       }   ///*////////////////////////////////////////////////////////////////////////////   ///   /// 查找函数   ///   /// 查找到链表list中第position个结点   /// LinkListNode* FindPosNode(LinkList *list, int position)   ///   /// 在链表list中找到currNode的前一个结点   /// LinkListNode *FindPrevNode(LinkList *list, LinkListNode *currNode)   ///   /// 判断结点node指向的区域是不是链表中的结点   /// int IsNodeInList(LinkList *list, LinkListNode *node)   ///   /// 找到数据域为data的结点首次出现的位置并返回结点信息   /// LinkListNode* FindNodeData(LinkList *list, ElemType data, int *position)   ///*////////////////////////////////////////////////////////////////////////////   LinkListNode* FindPosNode(LinkList *list, int position)      list    :   指向一个链表指针,此处传入表头地址      positon :   带查找的链表指针的位置      若成功返回指向待查找结点的指针      若失败返回NULL      查找到链表list中第position个结点  LinkListNode* FindPosNode(LinkList *list, int position)       assert(list != NULL);                                   // 链表不能为空       assert(position  = -1   position   list- m_length);   // 插入的w位置只能在[-1~length]       LinkListNode    *pNode  = list- m_head;       int             pos     = -1;       while(pNode != NULL   pos   position)       // 遍历单链表,找到第position个结点的位置       {           pNode = pNode- m_next;           pos++;       }       if(pNode == NULL || pos   position)       {           return NULL;       }       else       {   #ifdef DEBUG           printf("Find the %d point SUCCESS...[%p]\n", position, pNode);   #endif // DEBUG           return pNode;       }   LinkListNode *FindPrevNode(LinkList *list, LinkListNode *currNode);      list        :   指向一个链表指针,此处传入表头地址      currNode    :   待查找的链表指针的位置      若成功返回指向待查找结点的指针      若失败返回NULL      在链表list中找到currNode的前一个结点  LinkListNode *FindPrevNode(LinkList *list, LinkListNode *currNode)       assert(list !=  NULL);       assert(currNode != NULL);       LinkListNode *pNode = list- m_head;       while(pNode- m_next != NULL   pNode- m_next != currNode)       {           pNode = pNode- m_next;       }       if(pNode- m_next == currNode)                // 查找成功       {           return pNode;       }       else                                        // 查找失败       {           return NULL;       }   int IsNodeInList(LinkList *list, LinkListNode *node)      list    :   指向一个链表指针,此处传入表头地址      node    :   指向待查找的结点的指针      若成功 返回结点node在链表中的位置      若失败 返回-1      判断结点node指向的区域是不是链表中的结点  int IsNodeInList(LinkList *list, LinkListNode *node)       assert(list != NULL);                                   // 链表不能为空   assert(Node != NULL);                                   // 待查找的指针不能为空       LinkListNode    *pNode  = list- m_head;       int             pos     = -1;       while(pNode != NULL   pNode != node)       // 遍历单链表,找到第position个结点的位置       {           pNode = pNode- m_next;           pos++;       }       if(pNode == NULL)       {   // 查找成功           return -1;       }       else       {   // 查找失败   #ifdef DEBUG           printf("Find the [%p] point in the first %d pointer of the list...\n", fNode, pos);   #endif // DEBUG           return pos;       }   LinkListNode* FindData(LinkList *list, ElemType data, , int *position)      list    :   指向一个链表指针,此处传入表头地址      data    :   待查找的结点的数据信息      若成功 返回结点node在链表中的位置      若失败 返回-1      找到数据域为data的结点首次出现的位置并返回结点信息  LinkListNode* FindNodeData(LinkList *list, ElemType data, int *position)       LinkListNode *node = list- m_head- m_next;       int pos = 0;       while(node != NULL   node- m_data != data)       {           node = node- m_next;           pos++;       }       *position = pos;                // 将出现的位置传递回去       return node;                    // 返回结点的信息   ///*////////////////////////////////////////////////////////////////////////////   ///   /// 插入函数   ///   /// 将数据data插入链表的prevNode结点的下一个位置个位置   /// LinkListNode *AddNode(LinkList *list, LinkListNode *prevNode, ElemType data)   ///   /// 将数据data插入链表的第position个位置   /// LinkListNode *InsertNode(LinkList *list, int position, ElemType data)   ///*////////////////////////////////////////////////////////////////////////////   LinkListNode* AddNode(LinkList *list, LinkListNode *prevNode, ElemType data);      list        :   指向一个链表指针,此处传入表头地址      prevNode    :   待插入位置的前一个结点      data        :   待插入结点的数据      无      将数据data插入链表的prevNode结点的下一个位置个位置  LinkListNode *AddNode(LinkList *list, LinkListNode *prevNode, ElemType data)       assert(prevNode != NULL);                       // 插入点不能是空指针       LinkListNode *newNode = NULL;       if((newNode = (LinkListNode *)malloc(sizeof(LinkListNode))) == NULL)    // 为新结点开辟空间       {   // 开辟新结点失败           fprintf(stderr, "not enough memeory\n");           exit(EXIT_FAILURE);       }       //else       //{       // 开辟新结点成功       newNode- m_data = data;       newNode- m_next = NULL;       // 将指针newNode连接在pNode的后面       newNode- m_next = prevNode- m_next;       prevNode- m_next = newNode;       list- m_length++;                // 结点数目增加一个       list- m_head- m_data++;           // 头结点的数据域同样存储着结点总数       //}   #ifdef DEBUG       printf("The new node is inserted after point pointer[%p]\n", pNode);   #endif // DEBUG       return newNode;   void InsertNode(LinkList *list, int position, ElemType data)      list    :   指向一个链表指针,此处传入表头地址      positon :   待插入结点的位置      data    :   待插入结点的数据      无      将数据data插入链表的第position个位置  LinkListNode *InsertNode(LinkList *list, int position, ElemType data)       assert(list != NULL);       assert(position  =0   position   list- m_length + 1);       LinkListNode *prevNode = FindPosNode(list, position - 1);           // 找到待插入位置的前一个结点       LinkListNode *newNode = NULL;       // 下面调用InsertPointNode直接将结点插入到pNode结点后面       if((newNode = AddNode(list, prevNode, data)) != NULL)   // 将新的结点插入到待插入前一个指针的后面       {   // 插入成功           return newNode;                             // 返回新插入的结点   #ifdef DEBUG           printf("Insert the value %d into list at position %d...\n", data, position);   #endif // DEBUG       }       else       {           return NULL;                                // 插入失败返回NULL       }   //  //  以可以使用下面的代码   //  if((newNode = (LinkListNode *)malloc(sizeof(LinkListNode))) == NULL)    // 为新结点开辟空间   //  {   // 开辟新结点失败   //      fprintf(stderr, "not enough memeory\n");   //        exit(EXIT_FAILURE);   //  }   //  else   //  {   // 开辟新结点成功   //  newNode- m_data = data;   //  newNode- m_next = NULL;   //  // 将指针newNode连接在pNode的后面   //  newNode- m_next = prevNode- m_next;   //  prevNode- m_next = newNode;   //  list- m_length++;                // 结点数目增加一个   //  list- m_head- m_data++;           // 头结点的数据域同样存储着结点总数   //  }   ///*////////////////////////////////////////////////////////////////////////////   ///   /// 删除函数   ///   /// 删除链表list中prevNode结点之后的指针个指针   /// void DeleteNode(LinkList *list, int position)   ///   /// 删除链表list中prevNode结点之后的指针个指针   /// ElemType SubNode(LinkList *list, LinkListNode *prevNode)   ///   /// 删除链表list中prevNode结点之后的指针个指针   /// ElemType DeleteCurrNode(LinkList *list, LinkListNode *currNode)   ///*////////////////////////////////////////////////////////////////////////////   void DeleteNode(LinkList *list, int position)      list    :   指向一个链表指针,此处传入表头地址      positon :   待删除结点的位置      返回待删除结点的数据域      删除链表list中prevNode结点之后的指针个指针  ElemType DeleteNode(LinkList *list, int position)       assert(list != NULL);       assert(position  =0   position   list- m_length);       LinkListNode *prevNode = FindPosNode(list, position - 1);           // 找到第position - 1个结点       // 删除pNode的后一个结点       LinkListNode *delNode = prevNode- m_next;       ElemType delElem = delNode- m_data;       prevNode- m_next = delNode- m_next;       free(delNode);       list- m_length--;                // 结点数目减少一个       list- m_head- m_data--;           // 头结点的数据域同样存储着结点总数       return delNode;   ElemType DeleteCurrNode(LinkList *list, LinkListNode *currNode);      list    :   指向一个链表指针,此处传入表头地址      positon :   待删除结点的位置      返回待删除结点的数据域      删除链表list中prevNode结点之后的指针个指针  ElemType SubNode(LinkList *list, LinkListNode *prevNode)       assert(list != NULL);                       // 链表不能为空       assert(prevNode != NULL);                       // 待删除结点的前一个位置不能为空       assert(IsNodeInList(list, prevNode) != -1); // 待删除位置的前一个结点必须在链表中       // 删除pNode的后一个结点       LinkListNode *delNode = prevNode- m_next;       ElemType delElem = delNode- m_data;       prevNode- m_next = delNode- m_next;       free(delNode);       list- m_length--;                // 结点数目减少一个       list- m_head- m_data--;           // 头结点的数据域同样存储着结点总数       return delElem;   ElemType DeleteCurrNode(LinkList *list, LinkListNode *currNode);      list    :   指向一个链表指针,此处传入表头地址      positon :   待删除结点的位置      返回待删除结点的数据域      删除链表list中prevNode结点之后的指针个指针  ElemType DeleteCurrNode(LinkList *list, LinkListNode *currNode)       assert(list != NULL);                           // 链表不能为空       assert(currNode != NULL);                           // 待删除结点的前一个位置不能为空       assert(IsNodeInList(list, currNode) != -1); // 待删除的结点必须在链表中       ElemType delElem = -1;                          // 待删除结点的数据域       LinkListNode *delNode = NULL;                   // 指向将要删除的结点的指针       if(currNode- m_next != NULL)                 // 如果待删除结点不是最后一个结点       {           // 将currNode的后一个结点delNode作为删除结点,           delNode = currNode- m_next;           currNode- m_next = delNode- m_next;           //从链表中删除delNode           // 并将delNode的数据域保存到delNode中           delElem = currNode- m_data;                  // delElem保存currNode的数据域           currNode- m_data = delNode- m_data;           // 真正删除的结点其实是currNode下一个结点, 因此用currNode保存下一个结点的数据域       }       else                                            // 否则待删除结点是最后一个结点       {           // 直接将最后一个结点删除即可, 应该把其前一个结点的指针域赋值为空           delNode = currNode;           // 下面应该将currnNode的前一个结点的指针域赋值为空[时间复杂度O(n)]           LinkListNode *prevNode = FindPrevNode(list, currNode);           prevNode- m_next = NULL;       }       free(delNode);       list- m_length--;                // 结点数目减少一个       list- m_head- m_data--;           // 头结点的数据域同样存储着结点总数       return delElem;   ///*////////////////////////////////////////////////////////////////////////////   ///   /// 其他函数   ///   /// 显示单链表的信息   /// void ShowList(LinkList *list   ///   /// 删除链表list中prevNode结点之后的指针个指针   /// void SetNode(LinkList *list, int position, ElemType data)   ///   /// 获取单链表list第position个结点的数据域   /// ElemType GetNode(LinkList *list, int position)   ///   /// 获取单链表list的长度[即元素个数]   /// int LengthLinkList(LinkList *list)   ///   /// 判断当前链表是否是空链表   /// bool IsEmptyLinkList(LinkList *list)   ///*////////////////////////////////////////////////////////////////////////////   void ShowLinkList(LinkList *list)      list    :   指向一个链表指针,此处传入表头地址      无      显示单链表的信息  void ShowList(LinkList *list)   // assert(list- m_head != NULL)       if(list- m_head ==  NULL)            //  单链表可能没有被初始化       {           fprintf(stderr, "you cant SHOW the list without the list INITLINKLIST...\n");           return ;       }       printf("there are %d data in list\n", list- m_length);       if(list- m_length == 0)       {           return ;       }       LinkListNode *pNode = list- m_head- m_next;           // 从头指针开始遍历       while(pNode != NULL)                                //开始遍历单链表       {           printf("%d  ", pNode- m_data);           pNode = pNode- m_next;       }       printf("\n");   //  ElemType data;   //  for(int pos = 0; pos   list- m_length; pos++)   //  {   //      data = GetNode(list, pos);   //      printf("%d  ", data);   //  }   //  printf("\n");   void SetNode(LinkList *list, int position, ElemType data)      list    :   指向一个链表指针,此处传入表头地址      positon :   待修改的结点的数据      data    :   待更正的新数据域      无      修改单链表list第position个结点的数据域为data  void SetNode(LinkList *list, int position, ElemType data)       LinkListNode *pNode = FindPosNode(list, position);      // 找到单链表的第position个结点       pNode- m_data = data;   ElemType GetNode(LinkList *list, int position      list    :   指向一个链表指针,此处传入表头地址      positon :   待查询的结点的位置      获取到的结点数据      获取单链表list第position个结点的数据域  ElemType GetNode(LinkList *list, int position)       LinkListNode *pNode = FindPosNode(list, position);      // 找到单链表的第position个结点       return pNode- m_data;   int LengthLinkList(LinkList *list)      list    :   指向一个链表指针,此处传入表头地址      positon :   待查询的结点的位置      获取到的结点数据      获取单链表list的长度[即元素个数]  int LengthLinkList(LinkList *list)       return list- m_length;   bool IsEmptyLinkList(LinkList *list)      list    :   指向一个链表指针,此处传入表头地址      如果单链表是空表,返回true      否则返回false      判断当前链表是否是空链表  bool IsEmptyLinkList(LinkList *list)       return (list- m_length == 0);       // return (list- m_head- m_next == NULL);   #define LIST_SIZE 7   // 主函数   int main(void)       int pos;       printf("TEST 1...\n");       LinkList *plist = CreateLinkList( );                // 创建单链表       for(int pos = 0; pos   LIST_SIZE; pos++)         // 循环向单链表中插入数据       {           InsertNode(plist, pos, pos + 1);       }       ShowList(plist);                                    // 插入结束后显示单链表的信息       DeleteNode(plist, 0);                               // 删除第一个元素       ShowList(plist);       DeleteNode(plist, 1);                               // 删除第二个元素       ShowList(plist);       ClearLinkList(plist);                               // 将单链表清空       ShowList(plist);       DestroyLinkList(plist);                             // 将单链表销毁       plist = NULL;       printf("\n\nTEST 2...\n");       LinkList list;       InitLinkList( list);                                // 初始化单链表       for(int pos = 0; pos   LIST_SIZE; pos++)         // 训话向单链表中插入数据       {           InsertNode( list, pos, pos + 1);       }       ShowList( list);                                    // 显示单链表       ClearLinkList( list);                               // 清空单链表   //  FinitLinkList( list);       // ERROR== list- m_head- m_next == NULL       ShowList( list);       printf("\n\nTEST 3...\n");       LinkListNode *prevNode = list.m_head;       LinkListNode *addNode = NULL;       for(int pos = 0; pos   LIST_SIZE; pos++)       {           if((addNode = AddNode( list, prevNode, pos + 1)) != NULL)           {               prevNode = addNode;           }       }       ShowList( list);       while(IsEmptyLinkList( list) != true)           // 循环删除单链表中的数据       {           DeleteCurrNode( list, list.m_head- m_next);       }       ShowList( list);                                    // 显示单链表       return  EXIT_SUCCESS;  
c语言实现扫雷(含循环递归展开) 本笔记通过c语言实现扫雷小游戏(包含递归展开) 游戏实现逻辑位于test.c文件,整个游戏头文件位于game.h,游戏进程的具体操作于game.c中实现。
c语言实现三子棋(内含阅读思路,简单易实现) 本文如果按顺序来阅读可能不太好接受,建议阅读顺序为,由test.c的逻辑顺序读下去,遇见具体函数的实现跳转到game.c中来理解
c语言实现简单学生管理系统 该学生管理系统的实现是通过分文件的方式来写的,infor.h文件为头文件,源文件infor.c实现源文件test.c中封装函数,建议读者在做较大的系统是分文件来实现,可以提高代码的运行效率。