数据结构和算法—单链表

为什么我这么喜欢防御性编程和断言呢,因为他能对错误的参数及操作能过进行相应的操作,不至于程序崩溃

## 防御性编程

防御性编程(Defensive programming)是防御式设计的一种具体体现,它是为了保证,对程序的不可预见的使用,不会造成程序功能上的损坏。它可以被看作是为了减少或消除墨菲定律效力的想法。防御式编程主要用于可能被滥用,恶作剧或无意地造成灾难性影响的程序上。

断言

断言是编程术语,表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真,可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言而在部署时禁用断言。同样,程序投入运行后,最终用户在遇到问题时可以重新启用断言。

使用断言可以创建更稳定、品质更好且 不易于出错的代码。当需要在一个值为FALSE时中断当前操作的话,可以使用断言。单元测试必须使用断言

单链表的操作, 就像这个链子一样… 读者自己揣摩吧, 本人是真的懒…
在这里插入图片描述

初始化链表

就是把头节点的指针域置为NULL
在这里插入图片描述

前插法插入元素

头节点为 head 头节点的指针域为 head->next
插入节点为 node, 插入节点的指针域为 node->next

操作: node->next = head->next;
head->next = node;

在这里插入图片描述

尾插法插入元素

尾插法插入元素就只多了一步, 找到最后一个节点!!!
找到最后一个节点后 插入节点的指针域置为NULL (插入节点->next = NULL)
原先最后一个节点的指针域指向插入节点… (最后一个节点->next = 插入节点)

在这里插入图片描述

任意位置插入元素

**任意位置插入节点: 原理就是找到插入位置的前一个节点
插入节点的指针域指向该节点的下一个节点 (插入节点->next = 该节点->next)
把该节点的指针域指向插入节点 (该节点->next = 插入节点)
**

在这里插入图片描述

其他相关操作也和上述类似, 不明白的时候,画图可以让你更清晰或更迷茫, 哈哈哈哈哈哈哈!!!

单链表的基本操作

#include <iostream>
#include <Windows.h>
#include <stdio.h>

// #define MAX_SIZE	100	// 链表虽然是可以无限添加,但是得有一个上限!!!   这里就不是实现了

// 单链表的定义
typedef int ElemType;

typedef struct node {
	ElemType 	date;
	struct node     *next;	
}LinkList, LinkNode;

// 初始化链表
// 链表多种多样, 根据需求写相应的函数...
bool initList(LinkList** head) {
	(*head) = new LinkList;
	if(!*head) return false;
	
	(*head)->date = 0;		// 头节点可以使用也可以不使用( 可以存放元素 )
	(*head)->next = NULL;
	return true;
}

// 添加元素1(前插法)
bool linkInsertFront(LinkList** head, ElemType& e) {
	if(!*head) return false;
	
	LinkNode* p = new LinkNode;
	if(!p) return false;	
	p->date = e;

	p->next = (*head)->next;
	(*head)->next = p;
	return true;
}

// 添加元素2 (尾插法)
bool linkInsertBack(LinkList** head, ElemType& e) {
	if(!*head) return false;
	
	LinkNode* p = *head;
	LinkNode* s = NULL;

	while(p->next) {	// p->next 等NULL时 推出循环 p指向最后一个节点
		p = p->next;	
	}

	s = new LinkNode;
	if(!s) return false;
	s->date = e;

	s->next = NULL; // s->next = p->next;	// p->next 一定是NULL
	p->next = s;
	return true;
}

// 插入元素1 (按值插入) 插在该值的前面还是后面取决自己
// 这里是插在该值的后面
bool linkInsertNum(LinkList** head, ElemType& e, ElemType& num) {
	if(!*head || !(*head)->next) return false;	//判断是否存在节点

	LinkNode* p = (*head)->next;	// 指向第一个节点
	LinkNode* s = NULL;
	
	while(p) {
		if(p->date == num) break;
		p = p->next;
	}
	
	if(!p) return false;
	
	s = new LinkNode;
	if(!s) return false;

	s->date = e;
	s->next = p->next;
	p->next = s;
	return true;
}

// 插入元素 (按位置插入)  插在该位置的前面还是后面取决自己
// 这里是插在这个位置之前
bool listInsertSite(LinkList** head, ElemType& e, int site) {
	if(!*head) return false;
	if(site < 1) return false;
	
	LinkNode* p = *head;
	LinkNode* s = NULL;
	int count = 1;
	while(p && count < site) {
		p = p->next;
		count++;
	}

	if(!p) return false;	// 说明插入位置不存在(比如3个位置, 你要插在5的位置)
	
	s = new LinkNode;
	if(!s) return false;		
	s->date = e;

	s->next = p->next;
	p->next = s;
	return true;	
}

// 删除节点
bool linkDelete(LinkList** head, const int i) {
	if(!*head) return false;
	if(i<1) return false;

	LinkNode* p = *head;
	LinkNode* s = NULL;
	int count = 1;
	while(p && count < i) {	// 找到删除节点的前一个节点
		p = p->next;
		count++;
	}

	if(!p || !p->next) return false;
	
	s = p->next;
	p->next = s->next;	

	delete s;
	return true;	
}

//单链表的销毁
bool linkDestroy(LinkList** head) {
	if(!*head) return false;
	
	LinkNode* p = *head;
	while(p) {
		*head = p->next;
		delete p;
		p = *head;
	}
	
	*head = NULL;
	return true;
}

// 单链表的遍历
void linkPrint(LinkList* head) {
	if(!head || !head->next) return;

	while(head) {
		printf("%d ", head->date);
		head = head->next;	
	}
	printf("\n");
}
// 获取元素
bool linkGetElem(LinkList*head, ElemType& e, const int i) {
	if(!head) return false;
	if(i<1) return false;
	
	head = head->next;	// 指向第一个节点
	int count = 1;
	while(head&& count < i) {
		head = head->next;
		count++;
	}
	if(!head) return false;
		
	e = head->date;
	return true;
}

// 查找元素
int linkFindElem(LinkList* head, ElemType* e) {
	if(!head || !e) return -1;

	LinkNode* p = head->next;
	int count = 1;
	while(p) {
		if(p->date == *e) break;
		p = p->next;
		count++;
	}

	if(!p) return -1;

	return count;
}

// 测试代码就不写了, 懒虫上身, 在vs2019进行了简单的测试

嗯… 这个不是看的, 只是说明,我当时测试过了, 反正你们看不懂, 还是自己写测试代码吧!
在这里插入图片描述

**本文为本人学习过程, 欢迎大佬做出点评, 让我的不足之处得到改善,致敬IT大佬 **

测试的很马虎, 如果有什么问题, 欢迎提出, 因为我也不知道对不对!!!

发布了18 篇原创文章 · 获赞 2 · 访问量 230

猜你喜欢

转载自blog.csdn.net/weixin_44238530/article/details/102570961