链表的基本使用及注意事项

 C语言中的链表作为一个重要的知识点,也是必须要理解和会使用的,在此将自己的理解和学习过程做个记录。

个人觉得在进行链表的相关操作时首先要理解链表分三种,单向链表、双向链表、循环链表。

虽然说是三种,但其实本质都是一样的,就是在一个结构体里面有数据域和指针域,数据域中用来描述节点的信息,而指针域中用来指向上一个节点或者下一个节点,可以通俗的理解为就相当于一个盒子分成两部分。

以下是我实测过得代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

//创建数据结构体
typedef struct message{
int class;
int age;
}person;

//创建一个链表数据
typedef struct NODE{
person room1;
struct NODE * next;
}node,*list;

//创建一个链表头
list creat(void)
{
list head =(list)malloc(sizeof(node));
head->next =NULL;
return head;
}

//增加一个节点
bool add_node(list head,int type)
{
list pi =(list)malloc(sizeof(node));
if(type ==1)
{
person room2;
room2.class =9;
room2.age =18;
pi->room1=room2;
}
else if(type ==2)
{
person room3;
room3.class =8;
room3.age =24;
pi->room1=room3;
}
else
{
person room5;
room5.class=5;
room5.age =30;
pi->room1=room5;
}


pi->next=head->next;
head->next=pi;

return 1;
}

//删除一个节点
bool del_node(list head)
{

list prev =head;
list p =prev->next;
while(NULL != p)
{
//if(!strcmp(p->room1.age,24))
if(p->room1.age==24)
{
prev->next =p->next;
free(p);
return 1;

}
prev= p;
p =p->next;

}
return 0;


}


int main(int argc, char **argv)
{
person room4;
room4.class=7;
room4.age=20;

list head=creat();

add_node(head,1);
printf("head.name= %d\n",head->next->room1.age);
add_node(head,2);
printf("head.name= %d\n",head->next->room1.age);
printf("head.name= %d\n",head->next->next->room1.age);
add_node(head,3);
printf("head.name= %d\n",head->next->room1.age);
printf("head.name= %d\n",head->next->next->room1.age);
printf("head.name= %d\n",head->next->next->next->room1.age);
del_node(head);
printf("head.name= %d\n",head->next->room1.age);
printf("head.name= %d\n",head->next->next->room1.age);
return 0;

}
//打印结果为  18   24 18    30 24 18    30 18

这个代码中要注意,字符串的赋值如果直接赋值会报错。

struct student{
char name[10];
}

int main()
{

struct student stu1;
stu1.name ="xiaohu";//error 这样直接赋值是错误的 要用strcpy 字符串拷贝

char *pname ="xiaohu";
strcpy(stu1.name,pname);//ok
}

所以,修改后的代码为头插法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>


typedef struct class{

  char name[10];
  int class;
  int age;
}Student;

typedef struct NODE{

Student  stu;
struct NODE * next;
struct NODE * front;
}node,*list;

list creat(void)
{
  list head =(list)malloc(sizeof(node));
  head->next =NULL;
  return head;
}

bool add_node(list head,int type)
{
  list pi =(list)malloc(sizeof(node));
  if(type ==1)
    {
     Student stu1;
     stu1.class =9;
     stu1.age =18;
     char *pname1 = "xiaohu";
     strcpy(stu1.name,pname1);
     pi->stu=stu1;
    }
  else if(type ==2)
   {
     Student stu2;
     stu2.class =8;
     stu2.age =24;
     char *pname2 ="leyan";
     strcpy(stu2.name,pname2);;
     pi->stu=stu2;
   }
  else
   {
     Student stu3;
     stu3.class=5;
     stu3.age =30;
     char *pname3 ="rooik";
     strcpy( stu3.name,pname3);
     pi->stu=stu3;
   }


pi->next=head->next;
head->next=pi;

return 1;
}

bool del_node(list head)
{

list prev =head;
list p =prev->next;
while(NULL != p)
{
//if(!strcmp(p->room1.age,24))
if(p->stu.age==24)
{
prev->next =p->next;
free(p);
if(p=!NULL)
p=NULL;
return 1;
}
prev= p;
p =p->next;

}
return 0;


}




int main(int argc, char **argv)
{
Student stu4;
stu4.class=7;
stu4.age=20;
list head=creat();
add_node(head,1);
printf("head.name= %s head.age = %d head.class =%d\n",head->next->stu.name,head->next->stu.age,head->next->stu.class);
add_node(head,2);
printf("head.name= %s head.age = %d head.class =%d\n",head->next->stu.name,head->next->stu.age,head->next->stu.class);
printf("head.name= %s head.age = %d head.class =%d\n",head->next->next->stu.name,head->next->next->stu.age,head->next->next->stu.class);
add_node(head,3);
printf("head.name= %s head.age = %d head.class =%d\n",head->next->stu.name,head->next->stu.age,head->next->stu.class);
printf("head.name= %s head.age = %d head.class =%d\n",head->next->next->stu.name,head->next->next->stu.age,head->next->next->stu.class);
printf("head.name= %s head.age = %d head.class =%d\n",head->next->next->next->stu.name,head->next->next->next->stu.age,head->next->next->next->stu.class);
del_node(head);
printf("head.name= %s head.age = %d head.class =%d\n",head->next->stu.name,head->next->stu.age,head->next->stu.class);
printf("head.name= %s head.age = %d head.class =%d\n",head->next->next->stu.name,head->next->next->stu.age,head->next->next->stu.class);
return 0;

}

使用链表时要注意分配空间和释放,主义判断链表节点的一些关键信息,比如链表是否为空,当前节点是否存在,是头结点 尾结点还是中间节点等,我上面的程序只代表了最简单的情况,并没有考虑到实际应用中的各种情况,这一点需要注意。

1 链表要初始化,链表要记住头结点

2 每新建一个节点都需要分配内存,用malloc来分配,注意判断是否分配成功。

3 增加节点和删除节点时最好画图来理解和实操。

4 链表中可以增加其他数据成员,比如链表节点个数,等等。

经过修改后版本是

1 src/app.c

/**@file app.c
 * @note 
 * @brief  测试代码
 * 
 * @author   luoxi11
 * @date     20220707
 * @version  V1.0.0
 * 
 * @note ///Description here 
 * @note History:        
 * @note     <author>   <time>    <version >   <desc>
 * @note  
 * @warning  
 */
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <log_level.h>
#include <stdbool.h>

typedef struct class{

  char name[16];
  int class;
  int age;
}Student;

/* 定义好链表结构体 */
typedef struct NODE{

	Student  stu;
	struct NODE * next;
	struct NODE * front;
}node,*list;


/* 创建一个节点数据 */
Student creat_stu(void)
{
	Student new_stu;
	new_stu.class =9;
	new_stu.age =18;
	char *pname = "xiaohu";
	strcpy(new_stu.name,pname);

	return new_stu;
}



/*创建一个头结点*/
list creat_head(void)
{
  list head =(list)malloc(sizeof(node));
  head->next =NULL;
  return head;
}


/* 头插法新增一个节点 */
bool add_node(list head,Student st)
{
	 list new_node =(list)malloc(sizeof(node));

	 Student *st1=NULL;
	 st1=&st;
	 if(NULL!= st1)
	 {
	  new_node->stu=st;
	  new_node->next=head->next;
	  head->next=new_node;

	  return 1;
	 }
	 else
	 {
      LOG_ERROR("add_node error!\r\n");
	  return 0;
	 }
}


/* 删除一个固定的节点 */
bool del_node(list head,int age)
{
	list prev =head;    //定义一个节点一个人指向头节点
	list p =prev->next; //定义一个节点一个人指向头节点的下一个节点
	while(NULL != p)
	{
		if(p->stu.age >= age)
		{
			prev->next =p->next;
			free(p);
			if(NULL!=p)
			{
			 p=NULL;
			}
			return 1;
		}
		prev= p;
		p =p->next;
	}
	LOG_ERROR("del_node failed\r\n");
	return 0;

}




int main(int argc, char **argv)
{
	Student stu =creat_stu();
	list head=creat_head();
	add_node(head,stu);
	printf("head.name= %s head.age = %d head.class =%d\n",head->next->stu.name,head->next->stu.age,head->next->stu.class);
	add_node(head,stu);
	printf("head.name= %s head.age = %d head.class =%d\n",head->next->stu.name,head->next->stu.age,head->next->stu.class);
	printf("head.name= %s head.age = %d head.class =%d\n",head->next->next->stu.name,head->next->next->stu.age,head->next->next->stu.class);

	return 0;

}



include/log_level.h

/**@file log_level.h
 * @note 
 * @brief  
 * 
 * @author   luoxi
 * @date    20221014
 * @version  1.0
 * 
 * @note 设置日志打印等级
 * @note History:        
 * @note     <author>   <time>    <version >   <desc>
 * @note  
 * @warning  
 */
#ifndef _LOG_LEVEL_H_
#define _LOG_LEVEL_H_ 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h> 
#include <fcntl.h>
#include <stdlib.h>    
#include <stdarg.h>
#include <time.h>
#include <sys/stat.h>
#include <pthread.h>
#include <stdio.h>





#define __LOG_CN__ 1
#if __LOG_CN__

#define COLOR_END                       "\033[0m"
#define INFO_COLOR                      "\033[36m"
#define DEBUG_COLOR                     "\033[35m"
#define DEBUG_ARRAY_COLOR               "\033[35m"
#define WARNING_COLOR                   "\033[33m"
#define ERROR_COLOR                     "\033[31m"

#define LOG_LEVEL 1


typedef enum
{
    //用户可自定义打印格式
    LOG_LEVEL_CUSTOM = 0,
    //打印错误
    LOG_LEVEL_ERROR,
    //打印警告
    LOG_LEVEL_WARNING,
    //打印调试信息
    LOG_LEVEL_DEBUG,
    //打印数组信息
    LOG_LEVEL_DEBUG_ARRAY,
    //打印信息
    LOG_LEVEL_INFO,
}log_level_enum_t;

#define LOG_INFO(format,...)            do{\
                                            if (LOG_LEVEL >= LOG_LEVEL_INFO)\
                                            {\
                                                printf(INFO_COLOR"[INFO]:[FUNC]:%s, [LINE]:%04d:"format"\r\n"COLOR_END, __func__, __LINE__, ##__VA_ARGS__);\
                                            }\
                                        }while(0)

#define LOG_DEBUG(format,...)           do{\
                                            if (LOG_LEVEL >= LOG_LEVEL_DEBUG)\
                                            {\
                                                printf(DEBUG_COLOR"[DEBUG]:[FUNC]:%s, [LINE]:%04d:"format"\r\n"COLOR_END, __func__, __LINE__, ##__VA_ARGS__);\
                                            }\
                                        }while(0)

#define LOG_DEBUG_ARRAY(array, num)     do{\
                                            if (LOG_LEVEL >= LOG_LEVEL_DEBUG_ARRAY)\
                                            {\
                                                uint32_t i;\
                                                uint8_t *a = array;\
                                                printf(DEBUG_ARRAY_COLOR"[DEBUG_ARRAY]:[FUNC]:%s, [LINE]:%04d:\r\n"COLOR_END, __func__, __LINE__);\
                                                for (i = 0; i < num; i++)\
                                                {\
                                                    printf("%#X   ", a[i]);\
                                                    if ((i + 1 ) % 10 == 0)\
                                                    {\
                                                        printf("\r\n");\
                                                    }\
                                                }\
                                                printf("\r\n");\
                                            }\
                                        }while(0)

#define LOG_WARNING(format,...)           do{\
                                            if (LOG_LEVEL >= LOG_LEVEL_WARNING)\
                                            {\
                                                printf(WARNING_COLOR"[WARNING]:[FUNC]:%s, [LINE]:%04d:"format"\r\n"COLOR_END, __func__, __LINE__, ##__VA_ARGS__);\
                                            }\
                                        }while(0)

#define LOG_ERROR(format,...)           do{\
                                            if (LOG_LEVEL >= LOG_LEVEL_ERROR)\
                                            {\
                                                printf(ERROR_COLOR"[ERROR]:[FUNC]:%s, [LINE]:%04d:"format"\r\n"COLOR_END, __func__, __LINE__, ##__VA_ARGS__);\
                                            }\
                                        }while(0)

#define LOG_CUSTOM(format,...)          do{\
                                            if (LOG_LEVEL >= LOG_LEVEL_CUSTOM)\
                                            {\
                                                printf(format"\r\n", ##__VA_ARGS__);\
                                            }\
                                        }while(0)

#else

#define LOG_INFO(format,...)            do { } while (0)
#define LOG_DEBUG(format,...)           do { } while (0)
#define LOG_DEBUG_ARRAY(array, num)     do { } while (0)
#define LOG_WARNING(format,...)         do { } while (0)
#define LOG_ERROR(format,...)           do { } while (0)
#define LOG_CUSTOM(format,...)          do { } while (0)

#endif



#endif


Makefile

##
## Makefile
##
## History:
##     20221014 luoxi11 TEST
##     arm-ca9-linux-gnueabihf-gcc    F1plus
##     arm-mol-linux-uclibcgnueabihf-gcc    B1Pro B2    
##     arm-linux-gnueabihf-gcc

default: all
PWD			:= $(shell pwd)

ROOTDIR = ./

# 交叉编译工具
CC = $(TOOL_PREFIX)gcc
AR = $(TOOL_PREFIX)ar

INC_DIR += -I./include/
LIBFLGS = -lpthread

TARGET = release/app_test
CURPATH = $(shell pwd)
SOURCES = $(wildcard $(CURPATH)/src/*.c)

OBJECTS = $(patsubst %.c, %.o, $(SOURCES))

.PHONY: clean all

all : $(TARGET)

%.o:%.c
	$(CC) $(CFLAGS) $(INC_DIR) -c $^ -o $@


$(TARGET) : $(OBJECTS)
	echo -e $(OBJECTS)
	$(CC) $(OBJECTS) $(LIBFLGS) -o $(TARGET) 
	rm -f  $(OBJECTS)

clean:
	rm -f  $(OBJECTS)  $(TARGET)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值