二、C语言实现头结点的单链表

二、C语言实现头结点的单链表

1、头结点单链表(逻辑图)

二、C语言实现头结点的单链表

2、声明 

#pragma once


//结构声明
typedef int DataType;

//结点声明
typedef struct Node
{
	union //采用联合体的形式,开辟结点时二选一
	{
		DataType data;	//普通节点存储数据
		int length;     //头结点存储单链表的长度
	};

	struct Node* next;  //定义指向下一个结点的指针
}Linklist;



//方法声明

//单链表的初始化(头结点的初始化)
bool InitLinkList(Linklist* head);

//求单链表的长度
int LenghtOfLinkList(Linklist* head);

//申请新结点
Linklist* ApplyNewNode(Linklist* node, DataType value);

//插入:按位置插入(头结点与第一个结点之间的位置为0位置,最大位置不超过pos)
bool InsertOfPos(Linklist* head, DataType value, int pos);

//头插法
bool InsertOfHead(Linklist* head, DataType value);
//尾插法
bool InsertOfRear(Linklist* head, DataType value);


//按位置删除
bool DeleteOfPos(Linklist* head, int pos);
//头删法
bool DeleteOfHead(Linklist* head);
//尾删法
bool DeleteOfRear(Linklist* head);

//输出打印
void ShowAllNode(Linklist* head);

//单链表的销毁
bool DestroyList(Linklist* head);

3、方法实现

#include<stdio.h>
#include"headList.h"
#include<stdlib.h>
#include<malloc.h>

//单链表的初始化(头结点的初始化)
bool InitLinkList(Linklist* head)
{
	if (head == NULL) return false;

	head->length = 0;   //头结点开始存储单链表的结点个数为0
	head->next = NULL;  //头结点的next指向空

	return true;
}

//求单链表的长度
int LenghtOfLinkList(Linklist* head)
{
	if (head == NULL) exit(0);//exit(0);调用<stdlib.h>头文件

	return head->length;

}

//申请新结点
Linklist* ApplyNewNode(Linklist *node,DataType value)
{
	Linklist* new_node = (Linklist*)malloc(sizeof(Linklist));
	
	if (new_node == NULL) return NULL;

	new_node->data = value;
	new_node->next = node;

	return new_node;//返回申请成功的地址
}

//插入:按位置插入(头结点与第一个结点之间的位置为0位置,最大位置不超过pos)
bool InsertOfPos(Linklist* head, DataType value, int pos)
{
	if (head == NULL) return false;

	if (pos<0 || pos>LenghtOfLinkList(head)) return false;

	//找到pos位置的直接前驱
	Linklist* p = head;  //让p指向头结点

	while (pos)       //循环遍历找到pos的直接前驱
	{
		p = p->next;
		pos--;
	}

	Linklist* new_node =ApplyNewNode(p->next,value);//申请空间指的是让新结点指向p的直接后继结点(在堆区开辟新结点的空间)
	
	if (new_node == NULL) return NULL;
	p->next = new_node;
	head->length++;

	return true;
}

//头插法
bool InsertOfHead(Linklist* head, DataType value)
{
	if (head == NULL) return false;

	Linklist* new_node = ApplyNewNode(head->next, value);//与上面同理,让新结点的next域指向head的直接后继
	if (new_node == NULL) return false;

	head->next = new_node;   //连接前驱与新结点
	head->length++;          //长度++

	return true;
}


//尾插法
bool InsertOfRear(Linklist* head, DataType value)
{
	return InsertOfPos(head, value, head->length);
}

//按位置删除
bool DeleteOfPos(Linklist* head, int pos)
{
	if (head == NULL || pos<0 || pos>=head->length) return false;

	Linklist* p = head;
	//同理寻找pos位置的直接前驱
	while (pos)
	{
		p = p->next;
		pos--;
	}

	Linklist* q = p->next;//让q指向p的直接后继位置
	//将p->next指向q位置结点的直接后继
	p->next = q->next;

	free(q);
	//防止出现野指针
	head->length--;
	return true;
}


//头删法
bool DeleteOfHead(Linklist*head)
{
	return DeleteOfPos(head, 0);
}

//尾删法
bool DeleteOfRear(Linklist* head)
{
	if (head == NULL) return false;

	Linklist* p = head;
	Linklist* q = head->next;
	while (!q->next == NULL)
	{
		p = p->next;
		q = q->next;
	}
	free(q);
	p->next = NULL;//新尾结点置空
	head->length--;

	return true;
}

//按值删除,含有重复值的情况
bool DeleteOfValue(Linklist*head,DataType value)
{
	if (head == NULL) return false;

	Linklist* p = head;
	Linklist* q = head->next;

	while (q != NULL)
	{
		if (q->data == value)
		{
			p->next = q->next;
			free(q);
			q = p->next;
			head->length--;
		}
		else
		{
			p = q;
			q = q->next;
		}
	}
	return true;
}

//判空操作
bool IsEmpty(Linklist* head)
{
	if (head == NULL) exit(0);

	return head->length == 0;
}


//输出打印
void ShowAllNode(Linklist* head)
{
	if (head == NULL) exit(0);

	Linklist* p = head->next;

	while (p != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

//销毁单链表
bool DestroyList(Linklist* head)
{
	if (head == NULL) exit(0);

	while (!IsEmpty(head))
	{
		DeleteOfHead(head);
	}
	return true;
}


4、主函数测试

#include<stdio.h>
#include"headList.h"

int main()
{
	Linklist list;//在栈区定义一个单链表list
	InitLinkList(&list);

	printf("插入0-9\n");
	for (int i = 0; i < 10; i++)
	{
		InsertOfPos(&list,i,i);
	}
	ShowAllNode(&list);

	printf("头插法\n");
	InsertOfHead(&list,10);
	ShowAllNode(&list);

	printf("尾插法\n");
	InsertOfRear(&list, 66);
	ShowAllNode(&list);
	
	printf("按3位置删除\n");
	DeleteOfPos(&list,3);
	ShowAllNode(&list);

	printf("头删法\n");
	DeleteOfHead(&list);
	ShowAllNode(&list);

	printf("尾删法\n");
	DeleteOfRear(&list);
	ShowAllNode(&list);

	DestroyList(&list);
	

	return 0;
}

5、结束语

There is no development physically or intellectually without effort.

没有努力,就不会有身体上或智能上的成长。

                                                                                                                                                                                                                                                                           ——2021.03.10

上一篇:学习笔记:2.3 线性表的链式表示和实现(单链表详解)


下一篇:单链表反转