数据结构2-线性表的实现(C语言)

声明:线性表的实现使用的是.cpp文件。

  • 由于我使用的是vs2010,vs2010的编译器不支持函数返回值bool类型,并且不能这样定义for(int i= 0; i < 10; i++),必须在函数的开头声明i=0。为了编写的方便,我使用的是.cpp文件,没有使用.c文件。虽然是c++文件,但是内容是c语言。如果有需要.c文件的,请自行修改这两个地方就可以了。

1. 线性表的分类

* 按物理结构分
	1. 线性表物理结构是顺序结构:称为顺序表
		* 按数组是否动态分配
			1. 数组动态分配的顺序表
			2. 数组静态态分配的顺序表
	2. 线性表物理结构是链式结构:称为链表
		1. 单链表
		2. 双向链表
		3. 循环链表
			1. 循环单链表
			2. 循环双链表
		* 注意:以上链表都可以分为带头结点和不带头结点两种。

2. 数组静态分配的顺序表

2.1 目录结构

在这里插入图片描述

2.2 SeqList.h

//声明顺序表的最大长度
#define MAX_ISZE 255

// 1. 定义数据元素
typedef struct {
	int age;
	char * name;
} ElemType;

// 2. 定义顺序表
typedef struct {
	ElemType datas[MAX_ISZE];
	int length;
} SeqList;


/**
* func:初始化顺序表
* @seqList:顺序表
*/
void initSeqList(SeqList * seqList);


/**
* func:销毁顺序表
* @seqList:顺序表
*/
void destroySeqList(SeqList * seqList);


/**
* func:返回顺序表的长度
* @seqList:顺序表
*/
int length(SeqList * seqList);


/**
* func:定义在指定下标处添加元素
* @seqList:顺序表
* @index:指定的下标
* @elemType:要插入的元素
*/
bool insertElem(SeqList * seqList, int index, ElemType elemType);


/**
* func:定义删除指定下标的元素
* @seqList:顺序表
* @index:指定的下标
* return: 返回删除的元素
*/
bool deleteElem(SeqList * seqList, int index, ElemType * x);


/**
* func:定义修改某个下标的元素
* @seqList:顺序表
* @index:指定的下标
* @elemType:要修改成的元素
*/
bool updateElem(SeqList * seqList, int index, ElemType elemType);


/**
* func:定义查找某个下标的元素
* @seqList:顺序表
* @index:指定的下标
*/
bool selectElem(SeqList * seqList, int index, ElemType * x);


/**
* func:打印顺序表的所有元素
* @seqList:顺序表
* @index:指定的下标
*/
void printfSeqList(SeqList * seqList);


/**
* func:打印一个ElemType类型的元素
* @elem:要打印的元素
*/
void printElem(ElemType elem);

2.3 SeqList.cpp

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

/**
* func:初始化链表,将一个数组的所有数据放入一个链表中
* @seqList:顺序表
* @elemArray:存放数据的数组
* @length:elemArray数组存放数据的长度
*/
void initSeqList(SeqList * seqList) {
	//将顺序表的长度设置为0,否则回随机分配个值
	seqList->length = 0;
}


/**
* func:销毁顺序表
* @seqList:顺序表
*/
void destroySeqList(SeqList * seqList) {
	// 由于静态数组无法手动释放,所以将顺序表长度置为0表示释放顺序表
	seqList->length = 0;
}


/**
* func:返回顺序表的长度
* @seqList:顺序表
*/
int length(SeqList * seqList) {
	return seqList->length;
}


/**
* func:定义在指定下标处添加元素
* @seqList:顺序表
* @index:指定的下标
* @elemType:要插入的元素
*/
bool insertElem(SeqList * seqList, int index, ElemType elemType) {
	// 1. 判断传入的下标是否合法
	if (index<0 || index>=MAX_ISZE) {
		printf("您传入的下标越界!\n");
		return false;
	}
	// 2. 判断顺序表空间是否还足够
	if (seqList->length+1 > MAX_ISZE) {
		printf("链表空间不足!\n");
		return false;
	}
	// 3. 将index的后续元素后移
	for (int i = seqList->length-1; i >= index; i--) {
		seqList->datas[i+1] = seqList->datas[i];
	}
	// 4. 修改index处的数据元素
	seqList->datas[index] = elemType;
	// 5. 顺序表长度加1
	seqList->length++; 
	return true;
}


/**
* func:定义删除指定下标的元素
* @seqList:顺序表
* @index:指定的下标
* return: 返回删除的元素
*/
bool deleteElem(SeqList * seqList, int index, ElemType * x) {
	// 1. 判断传入的下标是否合法
	if (index<0 || index>=MAX_ISZE) {
		printf("您传入的下标越界!\n");
		return false;
	}
	// 2. 判断顺序表是否为空
	if (0 == length(seqList)) {
		printf("顺序表为空,无法删除元素!\n");
		return false;
	}
	// 3. 存放要删除的元素
	*x = seqList->datas[index];
	// 4. 将index的后续元素前移
	for (int i = index; i < seqList->length-1; i++) {
		seqList->datas[i] = seqList->datas[i+1];
	}
	// 5. 线性表长度减1
	seqList->length--;
	return true;
}


/**
* func:定义修改某个下标的元素
* @seqList:顺序表
* @index:指定的下标
* @elemType:要修改成的元素
*/
bool updateElem(SeqList * seqList, int index, ElemType elemType) {
	// 1. 判断传入的下标是否合法
	if (index<0 || index>=MAX_ISZE) {
		printf("您传入的下标越界!\n");
		return false;
	}
	// 2. 判断顺序表是否为空
	if (0 == length(seqList)) {
		printf("顺序表为空,无法更改元素!\n");
		return false;
	}
	// 3. 修改顺序表index处的元素
	seqList->datas[index] = elemType;
	return true;
}


/**
* func:定义查找某个下标的元素
* @seqList:顺序表
* @index:指定的下标
*/
bool selectElem(SeqList * seqList, int index, ElemType * x) {
	// 1. 判断传入的下标是否合法
	if (index<0 || index>=MAX_ISZE) {
		printf("您传入的下标越界!\n");
		return false;
	}
	// 2. 判断顺序表是否为空
	if (0 == length(seqList)) {
		printf("顺序表为空,无法更改元素!\n");
		return false;
	}
	*x = seqList->datas[index];
	return true;
}

/**
* func:打印顺序表的所有元素
* @seqList:顺序表
* @index:指定的下标
*/
void printfSeqList(SeqList * seqList) {
	for (int i = 0; i < seqList->length; i++) {
		printElem(seqList->datas[i]);
	}
}

/**
* func:打印一个ElemType类型的元素
* @elem:要打印的元素
*/
void printElem(ElemType elem) {
	printf("姓名:%s, 年龄:%d\n", elem.name, elem.age);
}

2.4 main.cpp

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

void main() {
	ElemType temp;
	ElemType elemArray[10];
	// 声明顺序表
	SeqList seqList;
	// 初始化顺序表
	initSeqList(&seqList);
	// 构造数组元素
	elemArray[0].name = "张三";
	elemArray[0].age = 13;
	elemArray[1].name = "李四";
	elemArray[1].age = 14;
	elemArray[2].name = "王五";
	elemArray[2].age = 15;


	//为顺序表增加一些值
	printf("[##############在顺序表的0,1,2位置插入元素##############]\n");
	insertElem(&seqList, 0, elemArray[0]);
	insertElem(&seqList, 1, elemArray[1]);
	insertElem(&seqList, 2, elemArray[2]);
	printfSeqList(&seqList);
	printf("当前顺序表长度为:%d\n", length(&seqList));
	//删
	printf("[###################删除index=1元素###################]\n");
	deleteElem(&seqList, 1, &temp);
	printf("删除的元素为:\n");
	printElem(temp);
	printf("顺序表元素为:\n");
	printfSeqList(&seqList);
	//改
	printf("[###################更改index=0元素###################]\n");
	temp.name = "帅帅";
	temp.age = 20;
	updateElem(&seqList, 0, temp);
	printf("顺序表元素为:\n");
	printfSeqList(&seqList);
	//查
	printf("[###################查看index=1元素###################]\n");
	selectElem(&seqList, 1, &temp);
	printElem(temp);
	//销毁顺序表
	destroySeqList(&seqList);
}

2.5 程序运行结果

在这里插入图片描述

2.6 几个注意点

  1. 由于静态数组无法手动释放,所以在销毁顺序表的函数中,将顺序表长度置为0表示释放顺序表。
  2. 使用顺序表时,每声明一个顺序表都需要及时的初始化顺序表。(将length置为0)
  3. 元素的删除和添加时要及时的修改顺序表长度。
  4. 在进行元素的删除和添加时有一个小结论,顺序表需要移动的元素,是从元素移动的方向开始移动。
  5. 顺序表添加元素示意图:
    在这里插入图片描述
  6. 顺序表删除元素示意图:
    在这里插入图片描述

3. 数组动态分配的顺序表

3.1 项目结构

在这里插入图片描述

3.2 SeqList.h

//声明顺序表的最大长度
#define MAX_ISZE 2

// 1. 定义数据元素
typedef struct {
	int age;
	char * name;
} ElemType;

// 2. 定义顺序表
typedef struct {
	ElemType * datas;
	int length;
} SeqList;


/**
* func:初始化顺序表
* @seqList:顺序表
*/
void initSeqList(SeqList * seqList);


/**
* func:销毁顺序表
* @seqList:顺序表
*/
void destroySeqList(SeqList * seqList);


/**
* func:动态的扩充顺序表的容量,每次扩充是上次容量的两倍
* @seqList:顺序表
*/
void enlarge(SeqList * seqList);


/**
* func:定义在指定下标处添加元素
* @seqList:顺序表
* @index:指定的下标
* @elemType:要插入的元素
*/
bool insertElem(SeqList * seqList, int index, ElemType elemType);


/**
* func:定义删除指定下标的元素
* @seqList:顺序表
* @index:指定的下标
*/
bool deleteElem(SeqList * seqList, int index, ElemType * x);


/**
* func:定义修改某个下标的元素
* @seqList:顺序表
* @index:指定的下标
* @elemType:要修改成的元素
*/
bool updateElem(SeqList * seqList, int index, ElemType elemType);


/**
* func:定义查找某个下标的元素
* @seqList:顺序表
* @index:指定的下标
*/
bool selectElem(SeqList * seqList, int index, ElemType * x);


/**
* func:打印顺序表的所有元素
* @seqList:顺序表
* @index:指定的下标
*/
void printfSeqList(SeqList * seqList);


/**
* func:打印一个ElemType类型的元素
* @elem:要打印的元素
*/
void printElem(ElemType elem);


/**
* func:返回顺序表的长度
* @seqList:顺序表
*/
int length(SeqList * seqList);



3.3 SeqList.cpp

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

/**
* func:初始化链表,将一个数组的所有数据放入一个链表中
* @seqList:顺序表
* @elemArray:存放数据的数组
* @length:elemArray数组存放数据的长度
*/
void initSeqList(SeqList * seqList) {
	// 将顺序表的长度设置为0,否则回随机分配个值
	seqList->length = 0;
	// 为顺序表动态分配数组
	seqList->datas = (ElemType *)malloc(MAX_ISZE * sizeof(ElemType));
}


/**
* func:销毁顺序表
* @seqList:顺序表
*/
void destroySeqList(SeqList * seqList) {
	seqList->length = 0;
	if (seqList->datas != NULL) {
		free(seqList->datas);
		seqList->datas = NULL;
	}
}


/**
* func:返回顺序表的长度
* @seqList:顺序表
*/
int length(SeqList * seqList) {
	return seqList->length;
}


/**
* func:动态的扩充顺序表的容量,每次扩充是上次容量的两倍
* @seqList:顺序表
*/
void enlarge(SeqList * seqList) {
	ElemType * temp = seqList->datas;
	// 动态开辟空间为原来两倍的数组
	printf("空间不够,分配一次空间,大小为:%d\n", seqList->length * 2);
	seqList->datas = (ElemType *)malloc(seqList->length * 2 * sizeof(ElemType));
	// 将元素复制到新的数组中
	for(int i = 0; i < seqList->length; i++)
		seqList->datas[i] = temp[i];
	// 手动释放数组内存
	free(temp);
	temp = NULL;
}

/**
* func:定义在指定下标处添加元素
* @seqList:顺序表
* @index:指定的下标
* @elemType:要插入的元素
*/
bool insertElem(SeqList * seqList, int index, ElemType elemType) {
	// 1. 判断传入的下标是否合法
	if (index<0 || index>MAX_ISZE) {
		printf("您传入的下标越界!\n");
		return false;
	}
	// 2. 判断顺序表空间是否还足够
	if (seqList->length+1 > MAX_ISZE) {
		//顺序表空间不足,动态开辟数组
		enlarge(seqList);
	}
	// 3. 将index的后续元素后移
	for (int i = seqList->length-1; i >= index; i--) {
		seqList->datas[i+1] = seqList->datas[i];
	}
	// 4. 修改index处的数据元素
	seqList->datas[index] = elemType;
	// 5. 顺序表长度加+
	seqList->length++;
	return true;
}


/**
* func:定义删除指定下标的元素
* @seqList:顺序表
* @index:指定的下标
* @x:记录要删除的元素
*/
bool deleteElem(SeqList * seqList, int index, ElemType * x) {
	// 1. 判断传入的下标是否合法
	if (index<0 || index>=MAX_ISZE) {
		printf("您传入的下标越界!\n");
		return false;
	}
	// 2. 判断顺序表是否为空
	if (0 == length(seqList)) {
		printf("顺序表为空!\n");
		return false;
	}
	// 3. 存放要删除的元素
	*x = seqList->datas[index];
	// 3. 将index的后续元素前移
	for (int i = index; i < seqList->length-1; i++) {
		seqList->datas[i] = seqList->datas[i+1];
	}
	// 4. 线性表长度加1
	seqList->length--;
	return true;
}


/**
* func:定义修改某个下标的元素
* @seqList:顺序表
* @index:指定的下标
* @elemType:要修改成的元素
*/
bool updateElem(SeqList * seqList, int index, ElemType elemType) {
	// 1. 判断传入的下标是否合法
	if (index<0 || index>=MAX_ISZE) {
		printf("您传入的下标越界!\n");
		return false;
	}
	// 2. 判断顺序表是否为空
	if (0 == length(seqList)) {
		printf("顺序表为空, 无法更改元素!\n");
		return false;
	}
	// 2. 修改顺序表index处的元素
	seqList->datas[index] = elemType;
	return true;
}


/**
* func:定义查找某个下标的元素
* @seqList:顺序表
* @index:指定的下标
*/
bool selectElem(SeqList * seqList, int index, ElemType * x) {
	// 1. 判断传入的下标是否合法
	if (index<0 || index>=MAX_ISZE) {
		printf("您传入的下标越界!\n");
		return false;
	}
	// 2. 判断顺序表是否为空
	if (0 == length(seqList)) {
		printf("顺序表为空, 无法查看元素!\n");
		return false;
	}
	*x = seqList->datas[index];
	return true;
}

/**
* func:打印顺序表的所有元素
* @seqList:顺序表
* @index:指定的下标
*/
void printfSeqList(SeqList * seqList) {
	for (int i = 0; i < seqList->length; i++) {
		printElem(seqList->datas[i]);
	}
}

/**
* func:打印一个ElemType类型的元素
* @elem:要打印的元素
*/
void printElem(ElemType elem) {
	printf("姓名:%s, 年龄:%d\n", elem.name, elem.age);
}



3.4 main.cpp

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


void main() {
	ElemType temp;
	ElemType elemArray[10];
	// 声明顺序表
	SeqList seqList;
	// 初始化顺序表
	initSeqList(&seqList);
	// 构造数组元素
	elemArray[0].name = "张三";
	elemArray[0].age = 13;
	elemArray[1].name = "李四";
	elemArray[1].age = 14;
	elemArray[2].name = "王五";
	elemArray[2].age = 15;


	//为顺序表增加一些值
	printf("[##############在顺序表的0,1,2位置插入元素##############]\n");
	insertElem(&seqList, 0, elemArray[0]);
	insertElem(&seqList, 1, elemArray[1]);
	insertElem(&seqList, 2, elemArray[2]);
	printfSeqList(&seqList);
	printf("当前顺序表长度为:%d\n", length(&seqList));
	//删
	printf("[###################删除index=1元素###################]\n");
	deleteElem(&seqList, 1, &temp);
	printf("删除的元素为:\n");
	printElem(temp);
	printf("顺序表元素为:\n");
	printfSeqList(&seqList);
	//改
	printf("[###################更改index=0元素###################]\n");
	temp.name = "帅帅";
	temp.age = 20;
	updateElem(&seqList, 0, temp);
	printf("顺序表元素为:\n");
	printfSeqList(&seqList);
	//查
	printf("[###################查看index=1元素###################]\n");
	selectElem(&seqList, 1, &temp);
	printElem(temp);
	//销毁顺序表
	destroySeqList(&seqList);
}

3.5 运行结果

在这里插入图片描述

3.6 几个注意点

1. 补充一些动态分配内存的一些知识。
	1. 使用malloc()函数可以动态在堆中分配内存,这些动态分配的内存只有两种情况下被释放:
		1. 手动使用free()函数释放。
		2. 程序结束时才会释放。
	2. free()函数用来手动释放堆内存,其有几个需要注意的地方:
		1. free()函数只能释放动态分配的内存。如果是静态的,比如int a[2] = {1, 2, 3}, 就不能使用free(a)释放。
		2. 如果将动态分配后地址的首地址给free(),他会将以这个地址为首的动态分配的地址全释放。
			比如动态分配了一个数组 int * a = (int *)malloc(sizeof(int)*3); 使用free(a);
			会将整个数组的内存全释放,而不是只释放一个单元。

2. 结构体变量间能够直接赋值,像基本类型一样。
	ElemType a, b;  //ElemType是结构体引用类型
	a.age = 15;
	a.name = "张三";
	b = a; //可以这样

3. 使用malloc时,一定要注意后边是前边的整数倍。

使用malloc时,一定要注意后边是前边的整数倍

数组动态分配的顺序表数组静态分配的顺序表差别不大,主要是在初始化、顺序表的释放以及空间不足时,处理的方法不一样。其他都一样。

4. 单链表的实现(带头结点)

4.1 项目结构

在这里插入图片描述

4.2 LinkList.h

// 定义抽象数据类型
typedef struct {
	char name[20];
	int age;
}ElemType;


// 定义结点
typedef struct LNode{
	ElemType data;
	struct LNode * next;
} LNode;

// 定义链表
typedef struct {
	int length;
	struct LNode head;
} LinkList;


/**
* func:初始化链表
* @linkList:链表头结点
*/
void initLinkList(LinkList * linkList);


/**
* func:释放链表
* @linkList:链表头结点
*/
void destroyList(LinkList * linkList);


/**
* func:在给定某节点的地址,在该节点的后面插入元素(后插)
* @index:给定某节点的地址
* @node:要插入的结点的地址
*/
void beforeInsertNode(LinkList * linkList, LNode * index, LNode * node);


/**
* func:在给定某节点的地址,在该节点的前面插入元素(前插)
* @index:给定某节点的地址
* @node:要插入的结点的地址
*/
void afterInsertNode(LinkList * linkList, LNode * index, LNode * node);


/**
* func:在链表末尾添加结点
* @node:要插入的结点的地址
*/
void insertNode(LinkList * linkList, LNode * node);


/**
* func:申请一个结点,并完善该节点的消息
*/
LNode * applyNode();



/**
* func:删除链表指定下标的元素
* @linkList:链表头结点
* @node:要删除的节点的地址
*/
void deleteNode(LinkList * linkList, LNode * node);


/**
* func:修改某节点的内容
* @node:要修改的节点的地址
*/
void updateNode(LNode * node);


/**
* func:判断两个结点的数据部分是否相等
* @node1:要判断的结点的地址
* @node2:要判断的结点的地址
*/
bool isEqual(LNode * node1, LNode * node2);


/**
* func:查找某个节点的位置,返回其地址
* @linkList:链表头结点
*/
LNode * selectNode(LinkList * linkList);


/**
* func:得到链表的长度
* @linkList:链表头结点
*/
int getLength(LinkList * linkList);


/**
* func:判断链表是否为空
* @linkList:链表头结点
*/
bool isEmpty(LinkList * linkList);


/**
* func:打印某个结点信息
* @node:要打印的链表的结点
*/
void printfNode(LNode * node);


/**
* func:打印整个链表的信息
* @linkList:链表头结点
*/
void printfLinkList(LinkList * linkList);

4.3 LinkList.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "LinkList.h"

/**
* func:初始化链表
* @linkList:链表头结点
*/
void initLinkList(LinkList * linkList) {
	linkList->length = 0;
	linkList->head.next = NULL;
}


/**
* func:释放链表
* @linkList:链表头结点
*/
void destroyList(LinkList * linkList) {
	// 用一个指针指向头结点
	LNode * temp = NULL;
	LNode * p = &linkList->head;

	// 如果链表不为空,则让其到第一个结点
	if (p->next != NULL)
		p = p->next;

	// 遍历链表,释放结点
	while (p->next != NULL) {
		p = p->next;
		temp = p;
		free(temp);
	}
	linkList->length = 0;
}


/**
* func:在给定某节点的地址,在该节点的后面插入元素(后插)
* @index:给定某节点的地址
* @node:要插入的结点的地址
*/
void afterInsertNode(LinkList * linkList, LNode * index, LNode * node) {
	node->next = index->next;
	index->next = node;
	// 链表长度加1
	linkList->length++;
}

/**
* func:在给定某节点的地址,在该节点的前面插入元素(前插)
* @index:给定某节点的地址
* @node:要插入的结点的地址
*/
void beforeInsertNode(LinkList * linkList, LNode * index, LNode * node) {
	// 先交换数据
	ElemType temp;
	temp = index->data;
	index->data = node->data;
	node->data = temp;
	//再利用尾插
	afterInsertNode(linkList, index, node);
}


/**
* func:在链表末尾添加结点
* @node:要插入的结点的地址
*/
void insertNode(LinkList * linkList, LNode * node) {
	LNode * p = &linkList->head;
	// 找到最后一个结点
	while (p->next != NULL)
		p = p->next;
	p->next = node;
	// 链表长度加1
	linkList->length++;
}


/**
* func:申请一个结点,并完善该节点的消息
*/
LNode * applyNode() {
	LNode * node = (LNode *)malloc(sizeof(LNode));
	node->next = NULL;
	printf("正在开辟一个新的结点...\n");
	printf("请输入姓名:");
	scanf("%s", node->data.name);
	printf("请输入年龄:");
	scanf("%d", &node->data.age);
	printf("新结点开辟成功!\n");
	return node;
}


/**
* func:删除链表中指定结点地址的元素
* @linkList:链表头结点
* @node:要删除的节点的地址
*/
void deleteNode(LinkList * linkList, LNode * node) {
	LNode * t;
	// 交换元素
	ElemType temp;
	temp = node->data;
	node->data = node->next->data;
	node->next->data = temp;
	// 删除结点
	t = node->next;
	node->next = t->next;
	free(t);
	// 链表长度减1
	linkList->length--;
}


/**
* func:修改某节点的内容
* @node:要修改的节点的地址
*/
void updateNode(LNode * node) {
	printf("正在修改一个结点...\n");
	printf("原姓名为:%s\n请输入新的姓名:", node->data.name);
	scanf("%s", node->data.name);
	printf("原年龄为:%d\n请输入年龄:", node->data.age);
	scanf("%d", &node->data.age);
	printf("结点修改成功!\n");
}


/**
* func:判断两个结点的数据部分是否相等
* @node1:要判断的结点的地址
* @node2:要判断的结点的地址
*/
bool isEqual(LNode * node1, LNode * node2) {
	if (strcmp(node1->data.name, node2->data.name) == 0 && node1->data.age == node2->data.age)
		return true;
	else
		return false;
}


/**
* func:查找某个节点的位置,返回其地址
* @linkList:链表头结点
*/
LNode * selectNode(LinkList * linkList) {
	// 先接受用户信息
	LNode node;
	printf("请输入要查找的姓名:");
	scanf("%s", node.data.name);
	printf("请输入要查找的年龄:");
	scanf("%d", &node.data.age);

	LNode * p = &linkList->head;
	while (p->next != NULL) {
		p = p->next;
		if (isEqual(p, &node))
			return p;
	}
	return NULL;
}


/**
* func:得到链表的长度
* @linkList:链表头结点
*/
int getLength(LinkList * linkList) {
	return linkList->length;
}


/**
* func:判断链表是否为空
* @linkList:链表头结点
*/
bool isEmpty(LinkList * linkList) {
	if (linkList->length >0) //或者 linkList->head.next != NULL
		return false;
	else
		return true;
}


/**
* func:打印某个结点信息
* @node:要打印的链表的结点
*/
void printfNode(LNode * node) {
	printf("\t姓名:%s\t年龄:%d\n", node->data.name, node->data.age);
}


/**
* func:打印整个链表的信息
* @linkList:链表头结点
*/
void printfLinkList(LinkList * linkList) {
	LNode * p = &linkList->head;
	int i = 1;
	while (p->next != NULL) {
		p = p->next;
		printf("第%d个结点信息为:", i);
		printfNode(p);
		i++;
	}
}

4.4 main.cpp

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

void main() {
	// 声明并初始化链表
	LinkList linkList;
	initLinkList(&linkList);

	// 开辟三个结点
	for (int i = 0; i < 3; i++) {
		insertNode(&linkList, applyNode());
	}
	printfLinkList(&linkList);
	int length = getLength(&linkList);
	printf("链表的长度为%d\n", length);
	
	// 开辟一个结点,分别前插在某个元素的前面
	LNode * t1 = applyNode();
	LNode * index = selectNode(&linkList);  // 查看元素
	beforeInsertNode(&linkList, index, t1);
	printfLinkList(&linkList);
	length = getLength(&linkList);
	printf("链表的长度为%d\n", length);

	//开辟一个结点,分别尾插在某个元素的后面
	LNode * t2 = applyNode();
	index = selectNode(&linkList);  // 查看元素
	afterInsertNode(&linkList, index, t2);
	printfLinkList(&linkList);
	length = getLength(&linkList);
	printf("链表的长度为%d\n", length);

	// 更改index结点
	updateNode(index);
	printfLinkList(&linkList);
	length = getLength(&linkList);
	printf("链表的长度为%d\n", length);

	// 删除index结点
	deleteNode(&linkList, index);
	printfLinkList(&linkList);
	length = getLength(&linkList);
	printf("链表的长度为%d\n", length);

	// 释放链表
	destroyList(&linkList);
}

4.5 程序运行结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43546676/article/details/105894787