【数据结构练习】单向链表实现、链表逆序实现

单向链表的实现,主要对链表进行CURD,由于是逻辑练习代码,所以实现删除、插入和查找功能的时候,传进去的是一个当作数组下标使用的整数。

主要难度在于链表逆转(要是双向的话就不用这么麻烦了,感觉又是一个典型的时间换空间例子),感觉逆转函数写得较为啰嗦和繁琐,效率较低,注释也不知道怎么写好(表达能力渣)。

插入和删除节点的代码有重复,本该抽象成一个函数了,但我实在懒,还是算了。

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

//定义节点的数据类型
typedef struct _node
{
	int data;
	struct _node* p_next;
}Node;

//定义单链表的数据类型
typedef struct _list
{
	//头指针,记录第一个元素
	Node* p_head;
	//尾指针,最后一个元素
	Node* p_end;
	int size;
}List;

//创建一个链表
void create_list(List** pp_list);

//创建一个节点
Node* create_node(int data);

//向链表头节点位置插入新节点
void push_head(List* p_list, int data);

//遍历链表中的所有元素
void travel(List* p_list);

//链表逆序
void reverse_list(List* P_list);

//计算链表中元素的个数
int size(List* p_list);

//清空链表中所有的节点
void clear(List* p_list);

//向指定的下标位置插入指定的节点,下标从0开始
void insert(List* p_list, int pos, int data);

//实现删除指定下标位置的节点操作
void del(List* p_list, int pos);

//删除头节点的功能
void pop_head(List* p_list);

//删除尾节点的功能
void pop_tail(List* p_list);

//判断链表是否为空
int empty(List* p_list);

//判断链表是否为满
int full(List* p_list);

//取得头节点的元素值
int get_head(List* p_list);

//取得尾节点的元素值
int get_tail(List* p_list);

//测试代码
int main(void)
{
	List* p_list = NULL;
	create_list(&p_list);
	int i = 0;
	while (i < 5)
	{
		push_head(p_list, i++);
	}
	travel(p_list);
	printf("%d\n", size(p_list));
	//clear(p_list);
	//printf("%d\n", size(p_list));
	insert(p_list, 2, 111);
	insert(p_list, 0, 222);
	insert(p_list, 7, 333);
	travel(p_list);
	printf("------------------------------------------------------------\n");
	del(p_list, 7);
	travel(p_list);
	printf("尾指针等于 %d\n", p_list->p_end->data);
	del(p_list, 5);
	travel(p_list);
	printf("尾指针等于 %d\n", p_list->p_end->data);
	del(p_list, 5);
	travel(p_list);
	printf("尾指针等于 %d\n", p_list->p_end->data);
	del(p_list, 4);
	travel(p_list);
	printf("尾指针等于 %d\n", p_list->p_end->data);

	return 0;
}

/*
   函数名:reverse_list
   功  能:链表逆序
   参  数:需要逆序的链表
*/
void reverse_list(List* p_list)
{
    Node* next = null;
    Node* prev = null;
    Node* head = p_list->p_head;

    while(head != NULL) 
    {
        next = head->next;
        head->next = prev;
        prev = head;
        head = next;
    }
}

//向链表头节点位置插入新节点
void push_head(List* p_list, int data)
{
	//创建新节点
	Node *p_node = create_node(data);
	if (NULL == p_list->p_head)
	{
		p_list->p_end = p_node;
	}
	//将新节点插入到头节点位置
	p_node->p_next = p_list->p_head;
	p_list->p_head = p_node;
	p_list->size++;
}

//遍历链表中的所有元素
void travel(List* p_list)
{
	Node *p_node = p_list->p_head;
	while (NULL != p_node)
	{
		printf("%d ", p_node->data);
		p_node = p_node->p_next;
	}
	printf("\n");
}

//创建一个链表
void create_list(List** pp_list)
{
	*pp_list = (List*)malloc(sizeof(List));
	(*pp_list)->p_head = NULL;
	(*pp_list)->p_end = NULL;
	(*pp_list)->size = 0;
}

//创建一个节点
Node* create_node(int data)
{
	Node* p_node = (Node*)malloc(sizeof(Node));
	p_node->p_next = NULL;
	p_node->data = data;
}

//计算链表中元素的个数
int size(List* p_list)
{
	return p_list->size;
}

//清空链表中所有的节点
void clear(List* p_list)
{
	Node *p_temp = NULL;
	while(NULL != p_list->p_head)
	{
		p_temp = p_list->p_head;	
		p_list->p_head = p_list->p_head->p_next;	
		free(p_temp);
		p_temp = NULL;
	}
	p_list->size = 0;
}

//向指定的下标位置插入指定的节点,下标从0开始
void insert(List* p_list, int pos, int data)
{
	if (pos < 0 || size(p_list) < pos)
	{
		printf("插入的节点的坐标不合法\n");
		return;
	}
	//创建一个新节点
	Node* p_node = create_node(data);
	if (0 == pos)
	{
		p_node->p_next = p_list->p_head;
		p_list->p_head = p_node;
		p_list->size++;
		p_list->p_end = p_node;
		return;
	}
	Node* p_temp = p_list->p_head;
	int i = 0;
	for (i = 0; i < pos - 1; i++)
	{
		p_temp = p_temp->p_next;
	}
	p_node->p_next = p_temp->p_next;
	p_temp->p_next = p_node;
	if (NULL == p_node->p_next)
	{
		p_list->p_end = p_node;
	}
	p_list->size++;
}

//实现删除指定下标位置的节点操作
void del(List* p_list, int pos)
{
	//判断删除的坐标是否合法以及链表是否为空
	if (pos < 0 || pos >= size(p_list))
	{
		printf("坐标不合法, 删除失败\n");
		return;
	}

	//当删除头节点时的处理方式
	Node *p_node = p_list->p_head;
	if (0 == pos)
	{
		p_list->p_head = p_node->p_next;	 
		free(p_node);
		p_list->size--;
		return;
	}

	//当删除其它位置节点时的处理方式
	int i = 0;
	//找出要删除的下标的前一个元素
	for (i = 0; i < pos - 1; i++)
	{
		p_node = p_node->p_next;
	}
	//记录要摧毁的节点的下一个节点
	Node *temp = p_node->p_next->p_next;
	free(p_node->p_next);
	//指向摧毁了的节点的下一个节点
	p_node->p_next = temp;
	//如果删除的元素是最后一个元素,改变尾指针的指向
	if (NULL == p_node->p_next)
	{
		p_list->p_end = p_node;
	}
	p_list->size--;
}


//删除头节点的功能
void pop_head(List* p_list)
{
	del(p_list, 0);
}

//删除尾节点的功能
void pop_tail(List* p_list)
{
	del(p_list, p_list->size - 1);
}

//判断链表是否为空
int empty(List* p_list)
{
	return 0 == p_list->size;
}

//判断链表是否为满
int full(List* p_list)
{
	return 0;
}

//取得头节点的元素值
int get_head(List* p_list)
{
	return p_list->p_head->data;
}

//取得尾节点的元素值
int get_tail(List* p_list)
{
	return p_list->p_end->data;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值