数据结构--单链表代码(王道书上代码手敲!!!)c++

目录

1.带头结点的初始化以及检查单链表是否为空

2.不带头结点的单链表初始化以及表是否为空检查

3.带头结点按位序插入

4.不带头结点的按位序插入

5.带头结点的后插,前插,按位删除,删除固定节点操作

6 不带头结点的后插,前插,按位删除,删除固定节点操作,

7.带头结点的单链表的查找(按位查找,按值查找,求表长)

8.不带头结点的单链表的查找(按位查找,按值查找,求表长) 

9.带头结点的尾插法,头插法,清空链表操作

10.不带头结点的尾插法,头插法,清空链表操作

11.带头结点的单链表的逆置

12.不带头结点的单链表逆置操作


​​​​​​

注意!!!以下代码是在c++环境中写的c代码,用了c++代码的&

1.带头结点的初始化以及检查单链表是否为空

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode* next;
}LNode,*LinkList;

//初始化
bool InitList(LinkList &L ) {
	//申请一篇空间来存储存储头节点,并使L指向这个节点
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL)
		return false;
	L->next = NULL;
	return true;
}

//检查单链表是否为空
bool Empty(LinkList L) {
	return (L->next==NULL);
 }

int main() {
//定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");
	return 0;
}

结果:

2.不带头结点的单链表初始化以及表是否为空检查

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//不带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode *next;
} LNode,*LinkList;

//初始化单链表
bool InitList(LinkList &L) {
	//头指针赋值为空
	L = NULL;
	return true;
}

//判断单链表是否为空
bool Empty(LinkList L) {
	return (L == NULL);
 }

int main() {
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n",Empty(L) ? "是":"否");
	return 0;
}

结果:

3.带头结点按位序插入

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode* next;
}LNode,*LinkList;

//初始化
bool InitList(LinkList &L ) {
	//申请一篇空间来存储存储头节点,并使L指向这个节点
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL)
		return false;
	L->next = NULL;
	return true;
}

//检查单链表是否为空
bool Empty(LinkList L) {
	return (L->next==NULL);
 }

//插入,在第i个位置插入元素e
bool InsertList(LinkList& L, int i, int e) {
	//判断i范围是否合法
	if (i < 1)
		return false;
	//定义一个指针指向当前扫描的结点,使其刚开始指向头结点(L在初始化的时候指向了头结点),
	LNode* p = L;
	int j = 0;//定义当前p指向的是第几个结点
	while (p != NULL && j < i - 1) {
		//此函数是为了寻找第i-1个节点
		p = p->next;
		j++;
	}
	//处理当插入位置的前一个节点(即第 i−1 个节点)不存在
	if (p == NULL)
		return false;
	LNode *s = (LNode *)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

int main() {
//定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");
	return 0;
}

结果跟上回一样,就不展示了

4.不带头结点的按位序插入

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
//不带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode *next;
} LNode,*LinkList;

//初始化单链表
bool InitList(LinkList &L) {
	//头指针赋值为空
	L = NULL;
	return true;
}

//判断单链表是否为空
bool Empty(LinkList L) {
	return (L == NULL);
 }

bool ListInsert(LinkList& L,int i,int e ) {
	if (i < 1)
		return false;
	//处理在第一个节点处插入
	if (i == 1) {
		LNode* s = (LNode*)malloc(sizeof(LNode));
		s->data = e;
		s->next = L;
		L = s;
		return true;
	}
	//处理在除第一个节点外插入,先找到该节点的前一个节点
	LNode* p;//指针p指向当前扫描到的节点
	int j = 1;//当前p指向的是第几个节点
	p = L;//p指向第1个节点(注意不是头结点)
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	if (p == NULL)//i太大
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

int main() {
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n",Empty(L) ? "是":"否");
	return 0;
}

结果和上回一样,就不贴图了

5.带头结点的后插,前插,按位删除,删除固定节点操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode* next;
}LNode,*LinkList;

//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, int e);
bool InsertNestNode(LNode* p, int e);
bool InsertPriorNode(LNode* p, int e);
bool ListDelete(LinkList& L, int i, int& e);
bool DeleteNode(LNode* p, int& e);
bool PrintList(LinkList L);

//初始化
bool InitList(LinkList &L ) {
	//申请一篇空间来存储存储头节点,并使L指向这个节点
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL)
		return false;
	L->next = NULL;
	return true;
}

//检查单链表是否为空
bool Empty(LinkList L) {
	return (L->next==NULL);
 }

//插入,在第i个位置插入元素e
bool InsertList(LinkList& L, int i, int e) {
	//判断i范围是否合法
	if (i < 1)
		return false;
	//定义一个指针指向当前扫描的结点,使其刚开始指向头结点(L在初始化的时候指向了头结点),
	LNode* p = L;
	int j = 0;//定义当前p指向的是第几个结点
	while (p != NULL && j < i - 1) {
		//此函数是为了寻找第i-1个节点
		p = p->next;
		j++;
	}
	return InsertNestNode(p, e);
}

//指定节点的后插操作,在p节点之后插入元素e
bool InsertNestNode(LNode *p, int e) {
	//处理当插入位置的前一个节点不存在
	if (p == NULL)
		return false;
	LNode* s = (LNode *)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next= s;
	return true;
}

//前插操作:在p结点前面插入元素e,(还是后插,只是把里面的数据换一下顺序)
bool InsertPriorNode(LNode *p,int e) {
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->next = p->next;	
	s->data = p->data;	//将p中的元素复制到s中
	p->next = s;	//新节点s连到p之后
	p->data = e;	//p中元素覆盖为e
	return true;
}

//按位序删除
bool ListDelete(LinkList& L, int i, int& e) {
	if (i < 1)
		return false;
	LNode* p;
	p = L;
	int j = 0;
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	LNode* q = p->next;
	p->next = q->next;
	e=q->data;
	free(q);
	return true;
}

//删除指定节点p
bool DeleteNode(LNode* p, int& e) {
	//此方法不能删除最后一个节点!注意,只能传入头指针从头遍历来删除最后的结点
	LNode* q = p->next;
	if(p == NULL||q==NULL)
	return false;
	p->data = q->data;	//和后继节点交换数据域
	p->next = q->next;	//将*q结点从链中“断开”
	free (q);			//释放后继节点的存储空间
	return true;
}

//打印单链表的元素
bool PrintList(LinkList L) {
	LNode* p = L;
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
	return true;
}

	int main() {
		// 定义头指针
		LinkList L;
		InitList(L);
		printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

		// 插入一些元素
		InsertList(L, 1, 10);
		InsertList(L, 2, 20);
		InsertList(L, 3, 30);
		InsertList(L, 2, 15); // 插入在第二个位置

		printf("链表内容:");
		PrintList(L);

		// 删除一些元素
		int e;
		ListDelete(L, 2, e); // 删除第二个位置的元素
		printf("删除第二个位置的元素:%d\n", e);

		printf("链表内容:");
		PrintList(L);

		// 在第一个节点前插入元素
		InsertPriorNode(L->next, 5);
		printf("在第一个节点前插入5:");
		PrintList(L);

		// 删除指定节点
		DeleteNode(L->next, e);
		printf("删除第一个节点后的节点,其值为:%d\n", e);

		printf("链表内容:");
		PrintList(L);
		return 0;
	}

结果:

6 不带头结点的后插,前插,按位删除,删除固定节点操作,

注:也就按位删除和带头结点的有区别,因为得考虑第一个节点

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
//不带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode *next;
} LNode,*LinkList;

//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, int e);
bool InsertNestNode(LNode* p, int e);
bool InsertPriorNode(LNode* p, int e);
bool ListDelete(LinkList& L, int i, int& e);
bool DeleteNode(LNode* p, int& e);
bool PrintList(LinkList L);

//初始化单链表
bool InitList(LinkList &L) {
	//头指针赋值为空
	L = NULL;
	return true;
}

//判断单链表是否为空
bool Empty(LinkList L) {
	return (L == NULL);
 }

bool InsertList(LinkList& L,int i,int e ) {
	if (i < 1)
		return false;
	//处理在第一个节点处插入
	if (i == 1) {
		LNode* s = (LNode*)malloc(sizeof(LNode));
		s->data = e;
		s->next = L;
		L = s;
		return true;
	}
	//处理在除第一个节点外插入,先找到该节点的前一个节点
	LNode* p;//指针p指向当前扫描到的节点
	int j = 1;//当前p指向的是第几个节点
	p = L;//p指向第1个节点(注意不是头结点)
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	return InsertNestNode(p, e);
}

//后插操作
bool InsertNestNode(LNode* p, int e) {
	//处理当插入位置的前一个节点不存在
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

//前插操作:在p结点前面插入元素e,(还是后插,只是把里面的数据换一下顺序)
bool InsertPriorNode(LNode* p, int e) {
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->next = p->next;
	s->data = p->data;	//将p中的元素复制到s中
	p->next = s;	//新节点s连到p之后
	p->data = e;	//p中元素覆盖为e
	return true;
}

//按位序删除
bool ListDelete(LinkList& L, int i, int& e) {
	if (i < 1)
		return false;
	// 删除第一个节点的特殊处理
	if (i == 1) {
		if (L == NULL)
			return false;
		LNode* q = L;
		e = L->data;
		L = L->next;
		free(q);
		return true;
	}
	LNode* p;
	p = L;
	int j = 0;
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	LNode* q = p->next;
	p->next = q->next;
	e = q->data;
	free(q);
	return true;
}

//删除指定节点p
bool DeleteNode(LNode* p, int& e) {
	//此方法不能删除最后一个节点!注意,只能传入头指针从头遍历来删除最后的结点
	LNode* q = p->next;
	if (p == NULL || q == NULL)
		return false;
	p->data = q->data;	//和后继节点交换数据域
	p->next = q->next;	//将*q结点从链中“断开”
	free(q);			//释放后继节点的存储空间
	return true;
}

//打印单链表的元素
bool PrintList(LinkList L) {
	LNode* p = L;
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
	return true;
}

int main() {
	// 定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入一些元素
	InsertList(L, 1, 10);
	InsertList(L, 2, 20);
	InsertList(L, 3, 30);
	InsertList(L, 2, 15); // 插入在第二个位置

	printf("链表内容:");
	PrintList(L);

	// 删除一些元素
	int e;
	ListDelete(L, 2, e); // 删除第二个位置的元素
	printf("删除第二个位置的元素:%d\n", e);

	printf("链表内容:");
	PrintList(L);

	// 在第一个节点前插入元素
	InsertPriorNode(L->next, 5);
	printf("在第一个节点前插入5:");
	PrintList(L);

	// 删除指定节点
	DeleteNode(L->next, e);
	printf("删除第一个节点后的节点,其值为:%d\n", e);

	printf("链表内容:");
	PrintList(L);
	return 0;
}

结果:

7.带头结点的单链表的查找(按位查找,按值查找,求表长)

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>


//带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode* next;
}LNode, * LinkList;


//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, int e);
bool InsertNestNode(LNode* p, int e);
bool InsertPriorNode(LNode* p, int e);
bool ListDelete(LinkList& L, int i, int& e);
bool DeleteNode(LNode* p, int& e);
bool PrintList(LinkList L);
LNode* GetElem(LinkList L, int i);
LNode* LocateElem(LinkList L, int e);
int Length(LinkList L);

//初始化
bool InitList(LinkList& L) {
	//申请一篇空间来存储存储头节点,并使L指向这个节点
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL)
		return false;
	L->next = NULL;
	return true;
}


//检查单链表是否为空
bool Empty(LinkList L) {
	return (L->next == NULL);
}


//插入,在第i个位置插入元素e
bool InsertList(LinkList& L, int i, int e) {
	//判断i范围是否合法
	if (i < 1)
		return false;
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	return InsertNestNode(p, e);
}


//指定节点的后插操作,在p节点之后插入元素e
bool InsertNestNode(LNode* p, int e) {
	//处理当插入位置的前一个节点不存在
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}


//前插操作:在p结点前面插入元素e,(还是后插,只是把里面的数据换一下顺序)
bool InsertPriorNode(LNode* p, int e) {
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->next = p->next;
	s->data = p->data;	//将p中的元素复制到s中
	p->next = s;	//新节点s连到p之后
	p->data = e;	//p中元素覆盖为e
	return true;
}


//按位序删除
bool ListDelete(LinkList& L, int i, int& e) {
	if (i < 1)
		return false;
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	LNode* q = p->next;
	p->next = q->next;
	e = q->data;
	free(q);
	return true;
}


//删除指定节点p
bool DeleteNode(LNode* p, int& e) {
	//此方法不能删除最后一个节点!注意,只能传入头指针从头遍历来删除最后的结点
	LNode* q = p->next;
	if (p == NULL || q == NULL)
		return false;
	p->data = q->data;	//和后继节点交换数据域
	p->next = q->next;	//将*q结点从链中“断开”
	free(q);			//释放后继节点的存储空间
	return true;
}


//打印单链表的元素
bool PrintList(LinkList L) {
	LNode* p = L->next;
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
	return true;
}


//按位查找,查找到第i个元素
LNode* GetElem(LinkList L, int i) {
	if (i < 0)//这必须是i<0,
//因为考虑到带头结点的调用此函数传入的参数是i-1,所以当插入第一个节点时,GetElem函数里面的i值为0,所以是i<0
//如果写写i<1,则在第一个位置插入则回返回null,最终插入失败。
		return NULL;
	LNode* p = L;
	int j = 0;//j是从0开始的,因为有头结点,默认头结点是第0个结点
	while (p != NULL && j < i) {
		p = p->next;
		j++;
	}
	return p;
}

//按值查找,根据e的值查找到e对应的指针
LNode* LocateElem(LinkList L,int e) {
	LNode* p = L->next;
	while (p != NULL && p->data != e) 
		p = p->next;
	return p;//找到就返回该节点指针,否则返回NULL
}

//求表的长度
int Length(LinkList L) {
	int len = 0;//表长
	LNode* p = L;
	while (p->next!=NULL) {
		p = p->next;
		len++;
	}
	return len;
}

int main() {
	// 定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入一些元素
	printf("%dhhh\n", InsertList(L, 1, 10));
	InsertList(L, 2, 20);
	InsertList(L, 3, 30);
	InsertList(L, 2, 15); // 插入在第二个位置

	printf("链表内容:");
	PrintList(L);

	// 删除一些元素
	int e;
	ListDelete(L, 2, e); // 删除第二个位置的元素
	printf("删除第二个位置的元素:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);

	// 在第一个节点前插入元素
	InsertPriorNode(L->next, 5);
	printf("在第一个节点前插入5:");
	PrintList(L);

	// 删除指定节点
	DeleteNode(L->next, e);
	printf("删除第一个节点后的节点,其值为:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);
	//按值查找元素的地址
	printf("20这个元素的地址为:%d\n", LocateElem(L, 20));
	printf("20元素标准地址:%d\n", GetElem(L, 2));
	//打印单链表的长度
	printf("表长为:%d", Length(L));
	return 0;
}

结果:

8.不带头结点的单链表的查找(按位查找,按值查找,求表长) 

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
//不带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode *next;
} LNode,*LinkList;

//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, int e);
bool InsertNestNode(LNode* p, int e);
bool InsertPriorNode(LNode* p, int e);
bool ListDelete(LinkList& L, int i, int& e);
bool DeleteNode(LNode* p, int& e);
bool PrintList(LinkList L);
LNode* GetElem(LinkList L, int i);
LNode* LocateElem(LinkList L, int e);
int Length(LinkList L);

//初始化单链表
bool InitList(LinkList &L) {
	//头指针赋值为空
	L = NULL;
	return true;
}

//判断单链表是否为空
bool Empty(LinkList L) {
	return (L == NULL);
 }

bool InsertList(LinkList& L,int i,int e ) {
	if (i < 1)
		return false;
	//处理在第一个节点处插入
	if (i == 1) {
		LNode* s = (LNode*)malloc(sizeof(LNode));
		s->data = e;
		s->next = L;
		L = s;
		return true;
	}
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	return InsertNestNode(p, e);
}

//后插操作
bool InsertNestNode(LNode* p, int e) {
	//处理当插入位置的前一个节点不存在
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

//前插操作:在p结点前面插入元素e,(还是后插,只是把里面的数据换一下顺序)
bool InsertPriorNode(LNode* p, int e) {
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->next = p->next;
	s->data = p->data;	//将p中的元素复制到s中
	p->next = s;	//新节点s连到p之后
	p->data = e;	//p中元素覆盖为e
	return true;
}

//按位序删除
bool ListDelete(LinkList& L, int i, int& e) {
	if (i < 1)
		return false;
	// 删除第一个节点的特殊处理
	if (i == 1) {
		if (L == NULL)
			return false;
		LNode* q = L;
		e = L->data;
		L = L->next;
		free(q);
		return true;
	}
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	LNode* q = p->next;
	p->next = q->next;
	e = q->data;
	free(q);
	return true;
}

//删除指定节点p
bool DeleteNode(LNode* p, int& e) {
	//此方法不能删除最后一个节点!注意,只能传入头指针从头遍历来删除最后的结点
	LNode* q = p->next;
	if (p == NULL || q == NULL)
		return false;
	p->data = q->data;	//和后继节点交换数据域
	p->next = q->next;	//将*q结点从链中“断开”
	free(q);			//释放后继节点的存储空间
	return true;
}

//打印单链表的元素
bool PrintList(LinkList L) {
	LNode* p = L;
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
	return true;
}

//按位查找,查找到第i个元素
LNode* GetElem(LinkList L,int i) {
	if (i < 1)
		return NULL;
	LNode* p = L;
	int j = 1;//j是从1开始的,因为没有头结点,直接从第一个节点开始了
	while (p != NULL && j < i) {
		p = p->next;
		j++;
	}
	return p;
}

//按值查找,根据e的值查找到e对应的指针
LNode* LocateElem(LinkList L, int e) {
	LNode* p = L->next;
	while (p != NULL && p->data != e)
		p = p->next;
	return p;//找到就返回该节点指针,否则返回NULL
}

//求表的长度
int Length(LinkList L) {
	int len = 0;//表长
	LNode* p = L;
	while (p != NULL) {
		p = p->next;
		len++;
	}
	return len;
}

int main() {
	// 定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入一些元素
	InsertList(L, 1, 10);
	InsertList(L, 2, 20);
	InsertList(L, 3, 30);
	InsertList(L, 2, 15); // 插入在第二个位置

	printf("链表内容:");
	PrintList(L);

	// 删除一些元素
	int e;
	ListDelete(L, 2, e); // 删除第二个位置的元素
	printf("删除第二个位置的元素:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);

	// 在第一个节点前插入元素
	InsertPriorNode(L->next, 5);
	printf("在第一个节点前插入5:");
	PrintList(L);

	// 删除指定节点
	DeleteNode(L->next, e);
	printf("删除第一个节点后的节点,其值为:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);
	//按值查找元素的地址
	printf("20这个元素的地址为:%d\n", LocateElem(L, 20));
	printf("20元素标准地址:%d\n",GetElem(L,2));
	//打印单链表的长度
	printf("表长为:%d", Length(L));
	return 0;
}

结果:

9.带头结点的尾插法,头插法,清空链表操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>


//带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode* next;
}LNode, * LinkList;


//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, int e);
bool InsertNestNode(LNode* p, int e);
bool InsertPriorNode(LNode* p, int e);
bool ListDelete(LinkList& L, int i, int& e);
bool DeleteNode(LinkList& L,LNode* p, int& e);
bool PrintList(LinkList L);
LNode* GetElem(LinkList L, int i);
LNode* LocateElem(LinkList L, int e);
int Length(LinkList L);
LinkList List_TailInsert(LinkList& L);
LinkList List_HeadInsert(LinkList& L);
void  CleanList(LinkList& L);

//初始化
bool InitList(LinkList& L) {
	//申请一篇空间来存储存储头节点,并使L指向这个节点
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL)
		return false;
	L->next = NULL;
	return true;
}


//检查单链表是否为空
bool Empty(LinkList L) {
	return (L->next == NULL);
}


//插入,在第i个位置插入元素e
bool InsertList(LinkList& L, int i, int e) {
	//判断i范围是否合法
	if (i < 1)
		return false;
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	return InsertNestNode(p, e);
}


//指定节点的后插操作,在p节点之后插入元素e
bool InsertNestNode(LNode* p, int e) {
	//处理当插入位置的前一个节点不存在
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	if (s == NULL)
		return false;
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}


//前插操作:在p结点前面插入元素e,(还是后插,只是把里面的数据换一下顺序)
bool InsertPriorNode(LNode* p, int e) {
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->next = p->next;
	s->data = p->data;	//将p中的元素复制到s中
	p->next = s;	//新节点s连到p之后
	p->data = e;	//p中元素覆盖为e
	return true;
}


//按位序删除
bool ListDelete(LinkList& L, int i, int &e) {
	if (i < 1)
		return false;
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	LNode* q = p->next;
	p->next = q->next;
	e = q->data;
	free(q);
	return true;
}


//删除指定节点p
bool DeleteNode(LinkList& L,LNode* p, int& e) {
	if (p == NULL)
		return false;
	if (p->next == NULL) {
		// 如果p是最后一个节点,找到p的前驱节点
		LNode* prev = L;
		while (prev->next != p) {
			prev = prev->next;
		}
		prev->next = NULL;
		e = p->data;
		free(p);
		return true;
	}
	else {
		LNode* q = p->next;
		if (p == NULL || q == NULL)
			return false;
		p->data = q->data;	//和后继节点交换数据域
		p->next = q->next;	//将*q结点从链中“断开”
		free(q);			//释放后继节点的存储空间
		return true;
	}
}


//打印单链表的元素
bool PrintList(LinkList L) {
	printf("当前链表内的元素如下:\n");
	LNode* p = L->next;
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
	return true;
}

//按位查找,查找到第i个元素
LNode* GetElem(LinkList L, int i) {
	if (i < 0)//这必须是i<0,
//因为考虑到带头结点的调用此函数传入的参数是i-1,所以当插入第一个节点时,GetElem函数里面的i值为0,所以是i<0
//如果写写i<1,则在第一个位置插入则回返回null,最终插入失败。
		return NULL;
	LNode* p = L;
	int j = 0;					//j是从0开始的,因为有头结点,默认头结点是第0个结点
	while (p != NULL && j < i) {
		p = p->next;
		j++;
	}
	return p;
}

//按值查找,根据e的值查找到e对应的指针
LNode* LocateElem(LinkList L,int e) {
	LNode* p = L->next;
	while (p != NULL && p->data != e) 
		p = p->next;
	return p;					//找到就返回该节点指针,否则返回NULL
}

//求表的长度
int Length(LinkList L) {
	int len = 0;//表长
	LNode* p = L;
	while (p->next!=NULL) {
		p = p->next;
		len++;
	}
	return len;
}

//尾插法建立单链表 法一r,s指针交替
LinkList List_TailInsert(LinkList &L) {
	int x;						//定义单链表中的数据类型
	L = (LNode*)malloc(sizeof(LNode));
	LNode* s, * r = L;
	printf("请您输入要插入的元素:");
	scanf("%d",&x);
	while (x!=9999) {			//输入9999表示结束
	s= (LNode*)malloc(sizeof(LNode));
	s->data = x;
	r->next = s;				//让s结点指向第一个元素的位置,r还是指向头结点
	r = s;						//r和s指向一样
	printf("请您输入要插入的元素:");
	scanf("%d", &x);
	}
	r->next = NULL;
	return L;
}

//头插法创建单链表,每回都在头结点后插
LinkList List_HeadInsert(LinkList &L) {
	int x;					//定义一个变量来存储要插入的值
	LNode* s;				//定义在循环外面,能加快程序的运行速度
	L = (LNode*)malloc(sizeof(LNode));
	L->next = NULL;
	printf("请您输入要插入的元素:");
	scanf("%d", &x);
	while (x!=9999) {		//输入9999表示结束
	s= (LNode*)malloc(sizeof(LNode));
	s->data = x;
	s->next= L->next;
	L->next = s;
	printf("请您输入要插入的元素:");
	scanf("%d", &x);
	}
	return L;
}

//清空表
void  CleanList(LinkList &L) {
	while (L->next!= NULL) {
	int e;
	ListDelete(L, 1, e);
	printf("删除的元素值为:%d\n", e);
	}
	PrintList(L);
}

int main() {
	// 定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入一些元素
	printf("%dhhh\n", InsertList(L, 1, 10));
	InsertList(L, 2, 20);
	InsertList(L, 3, 30);
	InsertList(L, 2, 15); // 插入在第二个位置

	printf("链表内容:");
	PrintList(L);

	// 删除一些元素
	int e;
	ListDelete(L, 2, e); // 删除第二个位置的元素
	printf("删除第二个位置的元素:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);

	// 在第一个节点前插入元素
	InsertPriorNode(L->next, 5);
	printf("在第一个节点前插入5:");
	PrintList(L);

	// 删除指定节点
	DeleteNode(L,L->next, e);
	printf("删除第一个节点后的节点,其值为:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);
	//按值查找元素的地址
	printf("20这个元素的地址为:%d\n", LocateElem(L, 20));
	printf("20元素标准地址:%d\n", GetElem(L, 2));
	//打印单链表的长度
	printf("表长为:%d\n", Length(L));

	
	//清空表
	printf("下面是清空表操作:\n");
	CleanList(L);

	// 检查链表是否为空
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	//检验后插法
	List_TailInsert(L);
	PrintList(L);

	//检验头插法
	CleanList(L);
	List_HeadInsert(L); 
	PrintList(L);

	return 0;
}

结果:

10.不带头结点的尾插法,头插法,清空链表操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
//不带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode *next;
} LNode,*LinkList;

//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, int e);
bool InsertNestNode(LNode* p, int e);
bool InsertPriorNode(LNode* p, int e);
bool ListDelete(LinkList& L, int i, int& e);
bool DeleteNode(LNode* p, int& e);
bool PrintList(LinkList L);
LNode* GetElem(LinkList L, int i);
LNode* LocateElem(LinkList L, int e);
int Length(LinkList L);
LinkList List_TailInsert(LinkList& L);
LinkList List_HeadInsert(LinkList& L);
void  CleanList(LinkList& L);

//初始化单链表
bool InitList(LinkList &L) {
	//头指针赋值为空
	L = NULL;
	return true;
}

//判断单链表是否为空
bool Empty(LinkList L) {
	return (L == NULL);
 }

bool InsertList(LinkList& L,int i,int e ) {
	if (i < 1)
		return false;
	//处理在第一个节点处插入
	if (i == 1) {
		LNode* s = (LNode*)malloc(sizeof(LNode));
		s->data = e;
		s->next = L;
		L = s;
		return true;
	}
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	return InsertNestNode(p, e);
}

//后插操作
bool InsertNestNode(LNode* p, int e) {
	//处理当插入位置的前一个节点不存在
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

//前插操作:在p结点前面插入元素e,(还是后插,只是把里面的数据换一下顺序)
bool InsertPriorNode(LNode* p, int e) {
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->next = p->next;
	s->data = p->data;	//将p中的元素复制到s中
	p->next = s;	//新节点s连到p之后
	p->data = e;	//p中元素覆盖为e
	return true;
}

//按位序删除
bool ListDelete(LinkList& L, int i, int& e) {
	if (i < 1)
		return false;
	// 删除第一个节点的特殊处理
	if (i == 1) {
		if (L == NULL)
			return false;
		LNode* q = L;
		e = L->data;
		L = L->next;
		free(q);
		return true;
	}
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	LNode* q = p->next;
	p->next = q->next;
	e = q->data;
	free(q);
	return true;
}

//删除指定节点p
bool DeleteNode(LNode* p, int& e) {
	//此方法不能删除最后一个节点!注意,只能传入头指针从头遍历来删除最后的结点
	LNode* q = p->next;
	if (p == NULL || q == NULL)
		return false;
	p->data = q->data;	//和后继节点交换数据域
	p->next = q->next;	//将*q结点从链中“断开”
	free(q);			//释放后继节点的存储空间
	return true;
}

//打印单链表的元素
bool PrintList(LinkList L) {
	LNode* p = L;
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
	return true;
}

//按位查找,查找到第i个元素
LNode* GetElem(LinkList L,int i) {
	if (i < 1)
		return NULL;
	LNode* p = L;
	int j = 1;//j是从1开始的,因为没有头结点,直接从第一个节点开始了
	while (p != NULL && j < i) {
		p = p->next;
		j++;
	}
	return p;
}

//按值查找,根据e的值查找到e对应的指针
LNode* LocateElem(LinkList L, int e) {
	LNode* p = L->next;
	while (p != NULL && p->data != e)
		p = p->next;
	return p;//找到就返回该节点指针,否则返回NULL
}

//求表的长度
int Length(LinkList L) {
	int len = 0;//表长
	LNode* p = L;
	while (p != NULL) {
		p = p->next;
		len++;
	}
	return len;
}

// 尾插法建立不带头节点的单链表
LinkList List_TailInsert(LinkList& L) {
	int x;             // 定义单链表中的数据类型
	LNode* s;          // 临时节点
	LNode* r = NULL;   // 尾指针初始化为空

	printf("请您输入要插入的元素:");
	scanf("%d", &x);

	L = NULL;          // 初始化为空表

	while (x != 9999) { // 输入9999表示结束
		s = (LNode*)malloc(sizeof(LNode));
		if (s == NULL) {
			printf("内存分配失败!\n");
			return L;
		}
		s->data = x;
		s->next = NULL;

		if (L == NULL) {
			L = s;     // 如果链表为空,第一个节点为头节点
		}
		else {
			r->next = s; // 否则,将新节点插入到尾部
		}
		r = s;         // 更新尾指针

		printf("请您输入要插入的元素:");
		scanf("%d", &x);
	}

	return L;
}


//头插法创建单链表,每回都在头结点后插
LinkList List_HeadInsert(LinkList& L) {
	int x;					//定义一个变量来存储要插入的值
	LNode* s;				//定义在循环外面,能加快程序的运行速度
	L = (LNode*)malloc(sizeof(LNode));
	L = NULL;
	printf("请您输入要插入的元素:");
	scanf("%d", &x);
	while (x != 9999) {		//输入9999表示结束
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		s->next = L;
		L = s;
		printf("请您输入要插入的元素:");
		scanf("%d", &x);
	}
	return L;
}

//清空表
void  CleanList(LinkList& L) {
	LNode* p;
	int e;
	while (L != NULL) {
		p = L;
		L = L->next;
		printf("删除的元素值为:%d\n", p->data);
		free(p);
	}
	PrintList(L);
}

int main() {
	// 定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入一些元素
	InsertList(L, 1, 10);
	InsertList(L, 2, 20);
	InsertList(L, 3, 30);
	InsertList(L, 2, 15); // 插入在第二个位置

	printf("链表内容:");
	PrintList(L);

	// 删除一些元素
	int e;
	ListDelete(L, 2, e); // 删除第二个位置的元素
	printf("删除第二个位置的元素:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);

	// 在第一个节点前插入元素
	InsertPriorNode(L->next, 5);
	printf("在第一个节点前插入5:");
	PrintList(L);

	// 删除指定节点
	DeleteNode(L->next, e);
	printf("删除第一个节点后的节点,其值为:%d\n", e);
	printf("链表内容:\n");
	PrintList(L);

	//按值查找元素的地址
	printf("20这个元素的地址为:%d\n", LocateElem(L, 20));
	printf("20元素标准地址:%d\n",GetElem(L,2));

	//打印单链表的长度
	printf("表长为:%d", Length(L));

	//清空表
	printf("下面是清空表操作:\n");
	CleanList(L);

	// 检查链表是否为空
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	//检验后插法
	List_TailInsert(L);
	PrintList(L);

	//检验头插法
	CleanList(L);
	List_HeadInsert(L);
	PrintList(L);

	return 0;
}

结果:

11.带头结点的单链表的逆置

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>


//带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode* next;
}LNode, * LinkList;


//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, int e);
bool InsertNestNode(LNode* p, int e);
bool InsertPriorNode(LNode* p, int e);
bool ListDelete(LinkList& L, int i, int& e);
bool DeleteNode(LinkList& L,LNode* p, int& e);
bool PrintList(LinkList L);
LNode* GetElem(LinkList L, int i);
LNode* LocateElem(LinkList L, int e);
int Length(LinkList L);
LinkList List_TailInsert(LinkList& L);
LinkList List_HeadInsert(LinkList& L);
void  CleanList(LinkList& L);
void ReverseList(LinkList& l);

//初始化
bool InitList(LinkList& L) {
	//申请一篇空间来存储存储头节点,并使L指向这个节点
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL)
		return false;
	L->next = NULL;
	return true;
}


//检查单链表是否为空
bool Empty(LinkList L) {
	return (L->next == NULL);
}


//插入,在第i个位置插入元素e
bool InsertList(LinkList& L, int i, int e) {
	//判断i范围是否合法
	if (i < 1)
		return false;
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	return InsertNestNode(p, e);
}


//指定节点的后插操作,在p节点之后插入元素e
bool InsertNestNode(LNode* p, int e) {
	//处理当插入位置的前一个节点不存在
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	if (s == NULL)
		return false;
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}


//前插操作:在p结点前面插入元素e,(还是后插,只是把里面的数据换一下顺序)
bool InsertPriorNode(LNode* p, int e) {
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->next = p->next;
	s->data = p->data;	//将p中的元素复制到s中
	p->next = s;	//新节点s连到p之后
	p->data = e;	//p中元素覆盖为e
	return true;
}


//按位序删除
bool ListDelete(LinkList& L, int i, int &e) {
	if (i < 1)
		return false;
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	LNode* q = p->next;
	p->next = q->next;
	e = q->data;
	free(q);
	return true;
}


//删除指定节点p
bool DeleteNode(LinkList& L,LNode* p, int& e) {
	if (p == NULL)
		return false;
	if (p->next == NULL) {
		// 如果p是最后一个节点,找到p的前驱节点
		LNode* prev = L;
		while (prev->next != p) {
			prev = prev->next;
		}
		prev->next = NULL;
		e = p->data;
		free(p);
		return true;
	}
	else {
		LNode* q = p->next;
		if (p == NULL || q == NULL)
			return false;
		p->data = q->data;	//和后继节点交换数据域
		p->next = q->next;	//将*q结点从链中“断开”
		free(q);			//释放后继节点的存储空间
		return true;
	}
}


//打印单链表的元素
bool PrintList(LinkList L) {
	printf("当前链表内的元素如下:\n");
	LNode* p = L->next;
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
	return true;
}

//按位查找,查找到第i个元素
LNode* GetElem(LinkList L, int i) {
	if (i < 0)//这必须是i<0,
//因为考虑到带头结点的调用此函数传入的参数是i-1,所以当插入第一个节点时,GetElem函数里面的i值为0,所以是i<0
//如果写写i<1,则在第一个位置插入则回返回null,最终插入失败。
		return NULL;
	LNode* p = L;
	int j = 0;					//j是从0开始的,因为有头结点,默认头结点是第0个结点
	while (p != NULL && j < i) {
		p = p->next;
		j++;
	}
	return p;
}

//按值查找,根据e的值查找到e对应的指针
LNode* LocateElem(LinkList L,int e) {
	LNode* p = L->next;
	while (p != NULL && p->data != e) 
		p = p->next;
	return p;					//找到就返回该节点指针,否则返回NULL
}

//求表的长度
int Length(LinkList L) {
	int len = 0;//表长
	LNode* p = L;
	while (p->next!=NULL) {
		p = p->next;
		len++;
	}
	return len;
}

//尾插法建立单链表 法一r,s指针交替
LinkList List_TailInsert(LinkList &L) {
	int x;						//定义单链表中的数据类型
	L = (LNode*)malloc(sizeof(LNode));
	LNode* s, * r = L;
	printf("请您输入要插入的元素:");
	scanf("%d",&x);
	while (x!=9999) {			//输入9999表示结束
	s= (LNode*)malloc(sizeof(LNode));
	s->data = x;
	r->next = s;				//让s结点指向第一个元素的位置,r还是指向头结点
	r = s;						//r和s指向一样
	printf("请您输入要插入的元素:");
	scanf("%d", &x);
	}
	r->next = NULL;
	return L;
}

//头插法创建单链表,每回都在头结点后插
LinkList List_HeadInsert(LinkList &L) {
	int x;					//定义一个变量来存储要插入的值
	LNode* s;				//定义在循环外面,能加快程序的运行速度
	L = (LNode*)malloc(sizeof(LNode));
	L->next = NULL;
	printf("请您输入要插入的元素:");
	scanf("%d", &x);
	while (x!=9999) {		//输入9999表示结束
	s= (LNode*)malloc(sizeof(LNode));
	s->data = x;
	s->next= L->next;
	L->next = s;
	printf("请您输入要插入的元素:");
	scanf("%d", &x);
	}
	return L;
}

//清空表
void  CleanList(LinkList &L) {
	int e;
	while (L->next!= NULL) {
	ListDelete(L, 1, e);
	printf("删除的元素值为:%d\n", e);
	}
	PrintList(L);
}

//逆置双链表
void ReverseList(LinkList& L) {
	if (L == NULL || L->next == NULL) {
		return; // 链表为空或只有一个元素时,无需逆置
	}

	LNode* prev = NULL;
	LNode* curr = L->next;
	LNode* next = NULL;

	while (curr != NULL) {
		next = curr->next; // 保存下一个节点
		curr->next = prev; // 当前节点指向前一个节点
		prev = curr;       // 前一个节点移动到当前节点
		curr = next;       // 当前节点移动到下一个节点
	}

	L->next = prev; // 头节点指向新的头节点
}

int main() {

	// 定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入一些元素
	printf("%dhhh\n", InsertList(L, 1, 10));
	InsertList(L, 2, 20);
	InsertList(L, 3, 30);
	InsertList(L, 2, 15); // 插入在第二个位置

	printf("链表内容:");
	PrintList(L);

	// 删除一些元素
	int e;
	ListDelete(L, 2, e); // 删除第二个位置的元素
	printf("删除第二个位置的元素:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);

	// 在第一个节点前插入元素
	InsertPriorNode(L->next, 5);
	printf("在第一个节点前插入5:");
	PrintList(L);

	// 删除指定节点
	DeleteNode(L, L->next, e);
	printf("删除第一个节点后的节点,其值为:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);
	//按值查找元素的地址
	printf("20这个元素的地址为:%d\n", LocateElem(L, 20));
	printf("20元素标准地址:%d\n", GetElem(L, 2));
	//打印单链表的长度
	printf("表长为:%d\n", Length(L));


	//清空表
	printf("下面是清空表操作:\n");
	CleanList(L);

	// 检查链表是否为空
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	//检验后插法
	List_TailInsert(L);
	PrintList(L);

	//检验头插法
	CleanList(L);
	List_HeadInsert(L); 
	PrintList(L);

	//检验逆置
	printf("下面是逆置操作:\n");
	ReverseList(L);
	PrintList(L);
	return 0;
}

结果:

 12.不带头结点的单链表逆置操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
//不带头节点的单链表
//定义结构体变量
typedef struct LNode {
	int data;
	struct LNode *next;
} LNode,*LinkList;

//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, int e);
bool InsertNestNode(LNode* p, int e);
bool InsertPriorNode(LNode* p, int e);
bool ListDelete(LinkList& L, int i, int& e);
bool DeleteNode(LNode* p, int& e);
bool PrintList(LinkList L);
LNode* GetElem(LinkList L, int i);
LNode* LocateElem(LinkList L, int e);
int Length(LinkList L);
LinkList List_TailInsert(LinkList& L);
LinkList List_HeadInsert(LinkList& L);
void  CleanList(LinkList& L);
void ReverseList(LinkList& L);

//初始化单链表
bool InitList(LinkList &L) {
	//头指针赋值为空
	L = NULL;
	return true;
}

//判断单链表是否为空
bool Empty(LinkList L) {
	return (L == NULL);
 }

bool InsertList(LinkList& L,int i,int e ) {
	if (i < 1)
		return false;
	//处理在第一个节点处插入
	if (i == 1) {
		LNode* s = (LNode*)malloc(sizeof(LNode));
		s->data = e;
		s->next = L;
		L = s;
		return true;
	}
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	return InsertNestNode(p, e);
}

//后插操作
bool InsertNestNode(LNode* p, int e) {
	//处理当插入位置的前一个节点不存在
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

//前插操作:在p结点前面插入元素e,(还是后插,只是把里面的数据换一下顺序)
bool InsertPriorNode(LNode* p, int e) {
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->next = p->next;
	s->data = p->data;	//将p中的元素复制到s中
	p->next = s;	//新节点s连到p之后
	p->data = e;	//p中元素覆盖为e
	return true;
}

//按位序删除
bool ListDelete(LinkList& L, int i, int& e) {
	if (i < 1)
		return false;
	// 删除第一个节点的特殊处理
	if (i == 1) {
		if (L == NULL)
			return false;
		LNode* q = L;
		e = L->data;
		L = L->next;
		free(q);
		return true;
	}
	LNode* p = GetElem(L, i - 1);//找到第i-1个结点
	if (p == NULL)
		return false;
	if (p->next == NULL)
		return false;
	LNode* q = p->next;
	p->next = q->next;
	e = q->data;
	free(q);
	return true;
}

//删除指定节点p
bool DeleteNode(LNode* p, int& e) {
	//此方法不能删除最后一个节点!注意,只能传入头指针从头遍历来删除最后的结点
	LNode* q = p->next;
	if (p == NULL || q == NULL)
		return false;
	p->data = q->data;	//和后继节点交换数据域
	p->next = q->next;	//将*q结点从链中“断开”
	free(q);			//释放后继节点的存储空间
	return true;
}

//打印单链表的元素
bool PrintList(LinkList L) {
	LNode* p = L;
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
	return true;
}

//按位查找,查找到第i个元素
LNode* GetElem(LinkList L,int i) {
	if (i < 1)
		return NULL;
	LNode* p = L;
	int j = 1;//j是从1开始的,因为没有头结点,直接从第一个节点开始了
	while (p != NULL && j < i) {
		p = p->next;
		j++;
	}
	return p;
}

//按值查找,根据e的值查找到e对应的指针
LNode* LocateElem(LinkList L, int e) {
	LNode* p = L->next;
	while (p != NULL && p->data != e)
		p = p->next;
	return p;//找到就返回该节点指针,否则返回NULL
}

//求表的长度
int Length(LinkList L) {
	int len = 0;//表长
	LNode* p = L;
	while (p != NULL) {
		p = p->next;
		len++;
	}
	return len;
}

// 尾插法建立不带头节点的单链表
LinkList List_TailInsert(LinkList& L) {
	int x;             // 定义单链表中的数据类型
	LNode* s;          // 临时节点
	LNode* r = NULL;   // 尾指针初始化为空

	printf("请您输入要插入的元素:");
	scanf("%d", &x);

	L = NULL;          // 初始化为空表

	while (x != 9999) { // 输入9999表示结束
		s = (LNode*)malloc(sizeof(LNode));
		if (s == NULL) {
			printf("内存分配失败!\n");
			return L;
		}
		s->data = x;
		s->next = NULL;

		if (L == NULL) {
			L = s;     // 如果链表为空,第一个节点为头节点
		}
		else {
			r->next = s; // 否则,将新节点插入到尾部
		}
		r = s;         // 更新尾指针

		printf("请您输入要插入的元素:");
		scanf("%d", &x);
	}

	return L;
}


//头插法创建单链表,每回都在头结点后插
LinkList List_HeadInsert(LinkList& L) {
	int x;					//定义一个变量来存储要插入的值
	LNode* s;				//定义在循环外面,能加快程序的运行速度
	L = (LNode*)malloc(sizeof(LNode));
	L = NULL;
	printf("请您输入要插入的元素:");
	scanf("%d", &x);
	while (x != 9999) {		//输入9999表示结束
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		s->next = L;
		L = s;
		printf("请您输入要插入的元素:");
		scanf("%d", &x);
	}
	return L;
}

//清空表
void  CleanList(LinkList& L) {
	LNode* p;
	while (L != NULL) {
		p = L;
		L = L->next;
		printf("删除的元素值为:%d\n", p->data);
		free(p);
	}
	PrintList(L);
}

//逆置双链表
void ReverseList(LinkList& L) {
	if (L == NULL || L->next == NULL) {
		return; // 链表为空或只有一个元素时,无需逆置
	}

	LNode* prev = NULL;
	LNode* curr = L;
	LNode* next = NULL;

	while (curr != NULL) {
		next = curr->next; // 保存下一个节点
		curr->next = prev; // 当前节点指向前一个节点
		prev = curr;       // 前一个节点移动到当前节点
		curr = next;       // 当前节点移动到下一个节点
	}

	L = prev; // 头节点指向新的头节点
}

int main() {
	// 定义头指针
	LinkList L;
	InitList(L);
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入一些元素
	InsertList(L, 1, 10);
	InsertList(L, 2, 20);
	InsertList(L, 3, 30);
	InsertList(L, 2, 15); // 插入在第二个位置

	printf("链表内容:");
	PrintList(L);

	// 删除一些元素
	int e;
	ListDelete(L, 2, e); // 删除第二个位置的元素
	printf("删除第二个位置的元素:%d\n", e);

	printf("链表内容:\n");
	PrintList(L);

	// 在第一个节点前插入元素
	InsertPriorNode(L->next, 5);
	printf("在第一个节点前插入5:");
	PrintList(L);

	// 删除指定节点
	DeleteNode(L->next, e);
	printf("删除第一个节点后的节点,其值为:%d\n", e);
	printf("链表内容:\n");
	PrintList(L);

	//按值查找元素的地址
	printf("20这个元素的地址为:%d\n", LocateElem(L, 20));
	printf("20元素标准地址:%d\n",GetElem(L,2));

	//打印单链表的长度
	printf("表长为:%d", Length(L));

	//清空表
	printf("下面是清空表操作:\n");
	CleanList(L);

	// 检查链表是否为空
	printf("查看单链表是否为空:%s\n", Empty(L) ? "是" : "否");

	//检验后插法
	List_TailInsert(L);
	PrintList(L);

	//检验头插法
	CleanList(L);
	List_HeadInsert(L);
	PrintList(L);

	//检验逆置
	printf("下面是逆置操作:\n");
	ReverseList(L);
	PrintList(L);
	return 0;
}

结果:

 结束~


有收获的宝宝留个赞赞再走吧~ 

不胜感激~

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
全集内容结构如下: ├─图 │ ├─关键路径(有向无环图及其应用2) │ │ 1.txt │ │ ALGraph.cpp │ │ ALGraph.h │ │ CriticalPath.cpp │ │ CriticalPath.h │ │ InfoType.cpp │ │ InfoType.h │ │ LinkList.cpp │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ Main.cpp │ │ SqStack.cpp │ │ SqStack.h │ │ Status.h │ │ VertexType.cpp │ │ VertexType.h │ │ │ ├─图的关节点 │ │ 1.txt │ │ ALGraph.cpp │ │ ALGraph.h │ │ FindArticul.cpp │ │ FindArticul.h │ │ InfoType.cpp │ │ InfoType.h │ │ LinkList.cpp │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ main.cpp │ │ Status.h │ │ VertexType.cpp │ │ VertexType.h │ │ │ ├─图的数组表示法 │ │ InfoType.cpp │ │ InfoType.h │ │ Main.cpp │ │ MGraph.cpp │ │ MGraph.h │ │ Status.h │ │ VertexType.cpp │ │ VertexType.h │ │ │ ├─图的遍历 │ │ ALGraph.cpp │ │ ALGraph.h │ │ DEBUG.txt │ │ InfoType.cpp │ │ InfoType.h │ │ LinkList.cpp │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ Main.cpp │ │ MGraph.cpp │ │ MGraph.h │ │ MTraverse.cpp │ │ MTraverse.h │ │ Status.h │ │ t1.txt │ │ t2.txt │ │ VertexType.cpp │ │ VertexType.h │ │ │ ├─图的邻接表存储结构 │ │ ALGraph.cpp │ │ ALGraph.h │ │ InfoType.cpp │ │ InfoType.h │ │ LinkList.cpp │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ Main.cpp │ │ Status.h │ │ t1.txt │ │ t2.txt │ │ VertexType.cpp │ │ VertexType.h │ │ │ ├─最短路径(从某个源点到其余各顶点的的最短路径) │ │ 1.txt │ │ 2.txt │ │ InfoType.cpp │ │ InfoType.h │ │ Main.cpp │ │ MGraph.cpp │ │ MGraph.h │ │ ShortestPath_DIJ.cpp │ │ ShortestPath_DIJ.h │ │ Status.h │ │ VertexType.cpp │ │ VertexType.h │ │ │ └─最短路径(每一对顶点间的最短路径) │ 1.txt │ 2.txt │ InfoType.cpp │ InfoType.h │ Main.cpp │ map.txt │ MGraph.cpp │ MGraph.h │ RailwaySearch.cpp │ ShortestPath_FLOYD.cpp │ ShortestPath_FLOYD.h │ Status.h │ VertexType.cpp │ VertexType.h │ ├─排序 │ ├─冒泡排序 │ │ 1.txt │ │ main.cpp │ │ RedType.cpp │ │ RedType.h │ │ Sq_BubbleSort.cpp │ │ Sq_BubbleSort.h │ │ │ ├─哈希表(哈希查找) │ │ ElemType.cpp │ │ ElemType.h │ │ HashTable.cpp │ │ HashTable.h │ │ main.cpp │ │ Records.txt │ │ │ ├─基数排序 │ │ 1.txt │ │ main.cpp │ │ SLL_RadixSort.cpp │ │ SLL_RadixSort.h │ │ │ ├─归并排序 │ │ 1.txt │ │ main.cpp │ │ RedType.cpp │ │ RedType.h │ │ sq_MergeSort.cpp │ │ sq_MergeSort.h │ │ │ ├─快速排序 │ │ 1.txt │ │ 2.txt │ │ 3.txt │ │ main.cpp │ │ RedType.cpp │ │ RedType.h │ │ Sq_QuitSort.cpp │ │ Sq_QuitSort.h │ │ │ ├─拓扑排序(有向无环图及其应用) │ │ 1.txt │ │ ALGraph.cpp │ │ ALGraph.h │ │ InfoType.cpp │ │ InfoType.h │ │ LinkList.cpp │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ Main.cpp │ │ SqStack.cpp │ │ SqStack.h │ │ Status.h │ │ TopologicalSort.cpp │ │ TopologicalSort.h │ │ VertexType.cpp │ │ VertexType.h │ │ │ ├─插入排序 │ │ 1.txt │ │ main.cpp │ │ RedType.cpp │ │ RedType.h │ │ Sq_InsertSort.cpp │ │ Sq_InsertSort.h │ │ │ ├─插入排序(希尔排序) │ │ main.cpp │ │ RedType.cpp │ │ RedType.h │ │ Sq_InsertSort.cpp │ │ Sq_InsertSort.h │ │ │ ├─插入排序(表插入排序) │ │ 1.txt │ │ main.cpp │ │ RedType.cpp │ │ RedType.h │ │ SL_InsertSort.cpp │ │ SL_InsertSort.h │ │ │ ├─选择排序(堆排序) │ │ 1.txt │ │ 2.txt │ │ 3.txt │ │ main.cpp │ │ RedType.cpp │ │ RedType.h │ │ Sq_HeapSort.cpp │ │ Sq_HeapSort.h │ │ │ ├─选择排序(树形选择排序) │ │ 1.txt │ │ main.cpp │ │ RedType.cpp │ │ RedType.h │ │ Sq_TreeSelectionSort.cpp │ │ Sq_TreeSelectionSort.h │ │ │ └─选择排序(简单选择排序) │ 1.txt │ main.cpp │ RedType.cpp │ RedType.h │ Sq_SelectSort.cpp │ Sq_SelectSort.h │ ├─查找 │ ├─动态查找表(二叉排序树) │ │ 1.txt │ │ BiTree.cpp │ │ BiTree.h │ │ DElemType.cpp │ │ DElemType.h │ │ DSTable.cpp │ │ DSTable.h │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ main.cpp │ │ QElemType.h │ │ Status.h │ │ TElmeType.h │ │ │ ├─平衡二叉树(二叉排序树的平衡旋转生成) │ │ 1.txt │ │ BBSTree.cpp │ │ BBSTree.h │ │ BiTree.cpp │ │ BiTree.h │ │ DElemType.cpp │ │ DElemType.h │ │ DSTable.cpp │ │ DSTable.h │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ main.cpp │ │ QElemType.h │ │ Status.h │ │ TElmeType.h │ │ │ ├─平衡的m路查找树—B_树 │ │ BTree.cpp │ │ BTree.h │ │ main.cpp │ │ Record.h │ │ Status.h │ │ │ ├─键树(Trie树) │ │ 1.txt │ │ main.cpp │ │ Record.h │ │ Status.h │ │ TrieTree.cpp │ │ TrieTree.h │ │ │ ├─键树(双链键树) │ │ 1.txt │ │ DLTree.cpp │ │ DLTree.h │ │ main.cpp │ │ Record.h │ │ Status.h │ │ │ ├─静态查找表(有序表的查找) │ │ 1.txt │ │ main.cpp │ │ SElemType.cpp │ │ SElemType.h │ │ SSTable.cpp │ │ SSTable.h │ │ Status.h │ │ │ ├─静态查找表(静态树表查找) │ │ 1.txt │ │ BiTree.cpp │ │ BiTree.h │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ main.cpp │ │ QElemType.h │ │ SElemType.cpp │ │ SElemType.h │ │ SSTable.cpp │ │ SSTable.h │ │ Status.h │ │ TElmeType.h │ │ │ └─静态查找表(顺序表的查找) │ 1.txt │ main.cpp │ SElemType.cpp │ SElemType.h │ SSTable.cpp │ SSTable.h │ Status.h │ ├─树 │ ├─二叉树的二叉链表存储 │ │ BiTree.cpp │ │ BiTree.h │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ main.cpp │ │ QElemType.h │ │ Status.h │ │ TElmeType.h │ │ │ ├─二叉树的顺序存储结构 │ │ main.cpp │ │ SqBiTree.cpp │ │ SqBiTree.h │ │ Status.h │ │ TELemType_define.cpp │ │ │ ├─哈夫曼树和哈夫曼编码 │ │ HuffmanTree.cpp │ │ HuffmanTree.h │ │ main.cpp │ │ Status.h │ │ │ ├─最小生成树 │ │ 1.txt │ │ InfoType.cpp │ │ InfoType.h │ │ Main.cpp │ │ MGraph.cpp │ │ MGraph.h │ │ MiniSpanTree_Kruskal.cpp │ │ MiniSpanTree_Kruskal.h │ │ MiniSpanTree_PRIM.cpp │ │ MiniSpanTree_PRIM.h │ │ Status.h │ │ VertexType.cpp │ │ VertexType.h │ │ │ ├─树的二叉链表 │ │ CSTree.cpp │ │ CSTree.h │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ main.cpp │ │ QElemType.h │ │ Status.h │ │ TElmeType.h │ │ │ ├─深度优先生成森林(无向图的连通性和生成树) │ │ ALGraph.cpp │ │ ALGraph.h │ │ CSTree.cpp │ │ CSTree.h │ │ DFSForest.cpp │ │ DFSForest.h │ │ InfoType.cpp │ │ InfoType.h │ │ LinkList.cpp │ │ LinkQueue.cpp │ │ LinkQueue.h │ │ Main.cpp │ │ QElemType.h │ │ Status.h │ │ TElmeType.h │ │ VertexType.cpp │ │ VertexType.h │ │ │ └─线索二叉树 │ BiThrTree.cpp │ BiThrTree.h │ main.cpp │ Status.h │ TElmeType.h │ └─表和数组 ├─KMP算法 │ Basic_operation_functions.h │ def_SString.h │ KMP.h │ main.cpp │ Status.h │ ├─n阶对称矩阵的压缩存储 │ Basic_operation_functions.h │ mian.cpp │ Status.h │ struct SyMatrix.h │ ├─三元组稀疏矩阵的压缩存储 │ Basic_operation_functions.h │ B_opera_fun_called_fun.h │ main.cpp │ Status.h │ struct TSMatrix.h │ Universal_main.h │ Universa_ts_b_opera_fun.h │ ├─不设头结点的单链表 │ LinkList.cpp │ LinkList.h │ main.cpp │ Status.h │ ├─串的堆存储结构 │ Basic_operation_functions.h │ HString.h │ Line_List.h │ main.cpp │ Status.h │ ├─串的定长顺序存储结构 │ Basic_operation_functions.h │ def_SString.h │ Main.cpp │ Status.h │ ├─广义表 │ GList.cpp │ GList.h │ main.cpp │ SString.cpp │ SString.h │ Status.h │ ├─数组 │ Basic_operation_functions.h │ main.cpp │ Status.h │ struct array.h │ ├─文本编辑(串和行表操作) │ Basic_operation_functions.h │ HString.h │ Line_List.h │ main.cpp │ Status.h │ ├─栈的顺序存储结构 │ main.cpp │ SqStack.cpp │ SqStack.h │ Status.h │ ├─走迷宫 │ Basic_called_functions.h │ Basic_operation_functions.h │ Main_Maze.cpp │ Status.h │ struct SqStack.h │ └─链队列 Basic_called_functions.cpp Basic_called_functions.h Basic_operation_functions.cpp main.cpp QElemType.h Status.h Struct_LinkQueue.h
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值