数据结构与算法——用C语言实现链表的初始化、增加节点、删除节点、查找节点等

       最近自己学习了线性表的链式表示和实现,其相关概念在《数据结构》——严蔚敏,教材中有详细的介绍。该篇文章主要是利用c语言中的结构体、指针等知识来实现链表的增、删、查、找的功能。

 一  、

     首先,链表中每个节点可定义为以下结构形式,如下:

typedef int Type; // 用Type代替 int, 方便修改数据类型

// 定义一个结构体类型,为一个链表节点
typedef struct Node {
	Type val;
	struct Node *next;
}Node;

       然后,创建包含一个指针变量的结构体,用来指向链表,即链表的头指针,如下。

// 创建一个指针,用来指向头
typedef struct SingList {
	struct Node *head;
}SingList;

        这是基本的两个结构,再声明要实现哪些功能函数,如下:

//链表初始化
void singleListInit(SingleList* sl);

// 创建接节点
Node* creatNode(Type val);
// 尾插
void listPushBack(SingleList* sl, Type val);
// 尾删
void listPopBack(SingleList* sl);
// 头插
void listPushFront(SingleList* sl, Type val);
// 头删
void listPopFront(SingleList* sl);
// pos位置后插入一个节点
void listInsertPos(Node* pos, Type val);
// 删除pos位置后的节点
void listDelPos(Node* pos);
// 查找
Node* listFind(SingleList* sl,Type val);
// 打印
void listPrint(SingleList* sl);
// 销毁
void listDestroy(SingleList* sl);

二、

再去实现各个功能函数,具体的全部代码整合后,如下代码所示:

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


typedef int Type; // 用Type代替 int

// 定义一个结构体类型,为一个链表节点
typedef struct Node {
	Type val;
	struct Node *next;
}Node;

// 创建一个指针,用来指向头
typedef struct SingList {
	struct Node *head;
}SingList;


// 初始化链表
void initList(SingList* sl) {
	Node* pHead = (Node*)malloc(sizeof(Node)); // 头节点
	sl->head = pHead;
	pHead->next = NULL;
}

// 创建一个节点 
Node* creatList(Type val) {
	Node* newNode = (Node*)malloc(sizeof(Node)); // 分配了一个空间 大小为node
	newNode->val = val;
	newNode->next = NULL; 
	return newNode;
}

// 头插
void listPushFront(SingList* sl, Type val) {
	Node* pHead = sl->head;
	Node* newNode = creatList(val);
	if (pHead->next == NULL) {  // 只有一个头节点, 往后接
		pHead->next = newNode;
	}
	else {
		newNode->next = pHead->next;
		pHead->next = newNode;
	}
}

// 头删
void listPopFront(SingList* sl) {
	Node* pHead = sl->head;
	if (pHead->next == NULL) {  //没有内容,直接返回
		return;
	}
	else {
		Node* first = pHead->next;
		pHead->next = first->next;
		free(first);
	}
}
// 尾插
void listPushBack(SingList* sl, Type val) {
	Node* pHead = sl->head;
	Node* newNode = creatList(val);
	Node* pTail = sl->head;
	// 如果是空,直接接后
	if (pHead->next == NULL) {
		pHead->next = newNode;
	}
	else {
		while (pTail->next != NULL) {
			pTail = pTail->next;   //找到尾节点
		}
		pTail->next = newNode;
	}
}
// 尾删
void listPopBack(SingList* sl) {
	Node* pHead = sl->head;
	Node* pTail = pHead;
	Node* prev = NULL;
	if (pHead->next == NULL) {
		return;
	}
	else {
		while (pTail->next != NULL) {
			prev = pTail;
			pTail = pTail->next;
		}
		prev->next = NULL;
		free(pTail);
	}
}

// 查找节点
Node* listFind(SingList* sl,Type val) {
	Node* pHead = sl->head;
	Node* cur = pHead;
	if (pHead->next == NULL) {
		return NULL;
	}
	else {
		while (cur->next) {
			if (cur->val == val) {
				return cur;
			}
			cur = cur->next;
		}

	}
	return NULL;
}

//插入指定节点后的一个节点
void listInsertPos(Node* pos, Type val) {
	Node* newNode = creatList(val);
	// 如果pos是尾节点
	if (pos->next == NULL) {
		pos->next = newNode;
	}
	else {   //如果不是尾节点
		newNode->next = pos->next;
		pos->next = newNode;
	}
}

// 删除指定节点后面的节点
void listDelPos(Node* pos) {
	// 如果是空,不删除
	if (pos->next == NULL) {
		return;
	}
	else {
		Node* next = pos->next;
		pos->next = next->next;
		free(next);
	}
}

// 销毁链表
void listDestory(SingList*sl) {
	Node* cur = sl->head->next;
	while (cur != sl->head) {
		Node* next = cur->next;
		free(cur);
		cur = next;
	}
	free(sl->head);
	sl->head = NULL;
}

//打印链表
void listPrint(SingList* sl) {
	Node* cur = sl->head->next;
	while (cur!=NULL) {
		printf("%d ", cur->val);
		cur = cur->next;
	}
	printf("\n\n");
}


int main() {
	SingList sl;
	initList(&sl);
	listPushFront(&sl, 1);
	listPushFront(&sl, 2);
	listPushFront(&sl, 3);
	listPushFront(&sl, 4); // 头插
	printf("四次头插的结果:");
	listPrint(&sl);   // 打印

	listPushBack(&sl,5);  // 尾插一个
	printf("尾插:");
	listPrint(&sl);  

	listPopBack(&sl);  // 尾删
	printf("尾删除:");
	listPrint(&sl);

	Node* pos = listFind(&sl, 3); // 查找

	listInsertPos(pos, 100);
	printf("pos后插入节点:");
	listPrint(&sl);

	listDelPos(pos); // 删除pos后的节点
	printf("删除pos后的节点:");
	listPrint(&sl);


	system("pause");
	return 0;
}




其运行结果是:

    四次头插的结果:4 3 2 1

    尾插:4 3 2 1 5

    尾删除:4 3 2 1

    pos后插入节点:4 3 100 2 1

    删除pos后的节点:4 3 2 1

    请按任意键继续. . .

所述代码如有错误,当然也会有更优化的方法,也请同志们多多指教,多多交流 !

发布了21 篇原创文章 · 获赞 2 · 访问量 861

猜你喜欢

转载自blog.csdn.net/weixin_44132627/article/details/105335051