04黑马数据结构笔记之(双向)循环企业链表(小挂钩)
1 思路:循环企业链表几乎与企业链表一样。何为循环,就是使链表的尾部不指向NULL,而指向链表的开头,即指向头结点,clist->head.next=&(clist->head); //使链表尾部指向头结点–循环。
同样以一个结构体管理链表,链表内使用挂钩连接存储数据。
//挂钩结构体
typedef struct CSNode{
struct CSNode *next;
}CircleSNode;
//管理链表结构体
typedef struct CList{
CircleSNode head;
int size;
}CircleList;
代码实现:
1)头文件.h:
#ifndef CIRCLELIST_H
#define CIRCLELIST_H
//挂钩结构体
typedef struct CSNode{
struct CSNode *next;
}CircleSNode;
//管理链表结构体
typedef struct CList{
CircleSNode head;
int size;
}CircleList;
//查找回调函数
typedef int (*MYCOMPAER)(CircleSNode *c1,CircleSNode *c2);
//打印回调函数
typedef void (*PRINT)(CircleSNode *c);
//链表初始化
CircleList *Init_CircleList();
//插入链表
int Insert_CircleList(CircleList *clist,int pos,CircleSNode *data);
//删除 -根据位置
int DelByPos_CircleList(CircleList *clist,int pos);
//删除 -根据值
int DelByValue_CircleList(CircleList *clist,CircleSNode *data,MYCOMPAER comp);
//查找
int Find_CircleList(CircleList *clist,CircleSNode *data,MYCOMPAER comp);
//打印
int Print_CircleList(CircleList *clist,PRINT print);
//获取第一个元素
CircleSNode *GetFront_CircleList(CircleList *clist);
//返回链表大小
int GetSize_CircleList(CircleList *clist);
//销毁内存
int Destory_CircleList(CircleList *clist);
#endif
2).cpp文件:
#include"CircleList.h"
#include<stdio.h>
#include<stdlib.h>
//链表初始化
CircleList *Init_CircleList(){
CircleList *clist=(CircleList*)malloc(sizeof(CircleList));
clist->head.next=&(clist->head); //使链表尾部指向头结点--循环
clist->size=0;
return clist;
}
//插入链表
int Insert_CircleList(CircleList *clist,int pos,CircleSNode *data){
if(clist==NULL){
return -1;
}
//数据为空也没必要插入
if(data==NULL){
return -1;
}
if(pos<0 || pos>clist->size){
pos=clist->size;
}
//插入
//先找到要插入前一节点
CircleSNode *pPre=&(clist->head);
for(int i=0;i<pos;i++){
pPre=pPre->next;
}
//开始插入
data->next=pPre->next;
pPre->next=data;
clist->size++;
return 0;
}
//删除 -根据位置
int DelByPos_CircleList(CircleList *clist,int pos){
if(clist==NULL){
return -1;
}
if(pos<0||pos>=clist->size){
printf("输入下标有误,数组越界了!\n");
return -1;
}
//删除
//找到要删除点的前一节点
CircleSNode *pPre=&(clist->head);
for(int i=0;i<pos;i++){
pPre=pPre->next;
}
//开始删除
pPre->next=pPre->next->next;
clist->size--;
return 0;
}
//删除 -根据值
int DelByValue_CircleList(CircleList *clist,CircleSNode *data,MYCOMPAER comp){
if(clist==NULL){
return -1;
}
if(data==NULL){
return -1;
}
/* while删除
int i=0;
CircleSNode *pPre=&(clist->head);
CircleSNode *pCur=clist->head.next;
while(pCur!=&(clist->head)){
if(comp(pCur,data)){
break;
}
pPre=pCur;
pCur=pCur->next;
i++;
}
//如果找到i肯定会少加一次1
if(i==clist->size){
printf("没有找到可删除的值\n");
return -1;
}
//开始删除
pPre->next=pCur->next;
*/
//for删除
CircleSNode *pPre=&(clist->head);
CircleSNode *pCur=clist->head.next;
for(int i=0;i<clist->size;i++){
if(comp(pCur,data)){
break;
}
pPre=pCur;
pCur=pCur->next;
}
//开始删除
pPre->next=pCur->next;
clist->size--;
return 0;
}
//查找
int Find_CircleList(CircleList *clist,CircleSNode *data,MYCOMPAER comp){
if(clist==NULL){
return -1;
}
if(data==NULL){
return -1;
}
int i=0;
CircleSNode *pCur=clist->head.next;
while(pCur!=&(clist->head)){
if(comp(pCur,data)){
break;
}
pCur=pCur->next;
i++;
}
//如果找到i肯定会少加一次1
if(i==clist->size){
printf("没有找到可删除的值\n");
return -1;
}
return i;
}
//打印
int Print_CircleList(CircleList *clist,PRINT print) {
if(clist==NULL){
return -1;
}
/*
CircleSNode *pCur=clist->head.next;
while(pCur!=&(clist->head)){
print(pCur);
pCur=pCur->next;
}
*/
CircleSNode *pCur=clist->head.next;
for(int i=0;i<clist->size;i++){
//多次打印,在打印之前,跳过头结点
if(pCur==&(clist->head)){
pCur=pCur->next;
}
print(pCur);
pCur=pCur->next;
}
return 0;
}
//获取第一个元素
CircleSNode *GetFront_CircleList(CircleList *clist){
return clist->head.next;
}
//返回链表大小
int GetSize_CircleList(CircleList *clist){
return clist->size;
}
//销毁内存
int Destory_CircleList(CircleList *clist){
if(clist==NULL){
return -1;
}
free(clist);
return 0;
}
3)主函数测试:
#include"CircleList.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//自定义类型
typedef struct Per{
CircleSNode node; //每个自定义类型都使用挂钩串联
char name[64];
int age;
}Person;
//打印回调函数
void MyPrint(CircleSNode *cs){
Person *p=(Person *)cs;
printf("名字:%s 年龄:%d\n",p->name,p->age);
}
//比较回调函数
int MyCompare(CircleSNode *cs1,CircleSNode *cs2){
Person *p1=(Person *)cs1;
Person *p2=(Person *)cs2;
if(strcmp(p1->name,p2->name)==0 &&p1->age==p2->age){
return 1;
}
return 0;
}
void test01(){
//创建链表
CircleList *clist=Init_CircleList();
//创建数据
Person p1,p2,p3,p4,p5;
strcpy(p1.name,"aaa");
strcpy(p2.name,"bbb");
strcpy(p3.name,"ccc");
strcpy(p4.name,"ddd");
strcpy(p5.name,"eee");
p1.age=20;
p2.age=18;
p3.age=16;
p4.age=66;
p5.age=22;
//插入数据
Insert_CircleList(clist,1000,(CircleSNode*)&p1);
Insert_CircleList(clist,1000,(CircleSNode*)&p2);
Insert_CircleList(clist,1000,(CircleSNode*)&p3);
Insert_CircleList(clist,1000,(CircleSNode*)&p4);
Insert_CircleList(clist,1000,(CircleSNode*)&p5);
//打印数据
Print_CircleList(clist,MyPrint);
//查找
printf("==========\n");
int pos = Find_CircleList(clist,(CircleSNode*)&p3,MyCompare);
printf("查找的数据下标为:%d\n",pos);
printf("==========\n");
//删除数据
DelByPos_CircleList(clist,2);
Print_CircleList(clist,MyPrint);
printf("==========\n");
DelByValue_CircleList(clist,(CircleSNode*)&p4,MyCompare);
Print_CircleList(clist,MyPrint);
//销毁内存
Destory_CircleList(clist);
}
int main(){
test01();
return 0;
}
总结循环链表:使尾节点不指向空,指向头结点。