数据结构 链表的构建

本文详细介绍了链表的数据结构,包括节点的struct定义、链表的创建与赋值,以及对链表的各种操作如插入、删除和显示。文章通过示例代码展示了如何创建链表,以及在链表中插入节点、删除特定位置或值的节点等操作。
摘要由CSDN通过智能技术生成

经历了两天的理解,终于弄明白了链表List的底层逻辑,便是定义结构体,给结构体附上value值和下一个节点的指针,我不禁想 是否所有的 数据结构 都可以用struct来定义呢?我不着急知道答案,而是会循序渐进,弄清楚代码的世界。

链表的构建 包含了几点:

1)节点的struct定义;

2)链表的定义 >> 链表的赋值操作;

3)对链表的操作;

首先, 节点 包含value值,由于节点不像数组一样是连续存储的,因此想要找到一个链表内的所有元素需要知道其所有元素的地址,而数组呢,只需要知道首地址以及数组的长度即可。

其次,链表的定义,链表大致分为两种 第一种是有头(空)节点的,第二种是没有头节点的,怎么去描述呢 没有头节点的就像一个结构体数组,包含了value值和next的地址,而有头(空)节点的相当于这数组前添加了一项,但它没有数值,只是包含了next的地址,因此在实际操作中要略过头节点。

最后 链表的操作,这里没什么好说的,类似于类与对象的操作,struct 结构体和 class 类 还是有很多相似之处的。

下面看构建链表的代码:

#include<iostream>
using namespace std;
struct Node {
	int value;
	Node* Next;
};
struct Node* List_creat(int a[], int n) {
	Node* List = (Node*)malloc(sizeof(Node));
	if (List == NULL) {
		cout << "创建失败!";
		return NULL;
	}
	Node* p = List;
	for (int i = 0; i <= n - 1; i++) {
		Node* temp = (Node*)malloc(sizeof(Node));
		temp->value = a[i];
		p->Next = temp;
		p = p->Next;
	}
	p->Next = NULL;
	return List;
}
void deletepos(Node* List, int pos);
void deletevalue(Node* List);
void display(Node* List);
int showmeposvalue(Node* List,int pos);
void insert_front(Node* List);
void insert_back(Node* List);
int main() {
	int a[5] = { 1,2,3,4,5 };
	int size = sizeof(a) / sizeof(a[0]);
	Node *List = List_creat(a, 5);
	display(List);
	deletepos(List, 3);
	display(List);
	insert_front(List);
	display(List);
	cout << "Second pos's value:" << showmeposvalue(List, 2) << endl;
	insert_back(List);
	display(List);
	deletevalue(List);
	return 0;
}
void deletepos(Node* List, int pos) {
	Node* current = List;
	Node* temp = List->Next;
	for (int i = 0; i <= pos - 2; i++) {
		current = current->Next;
		temp = temp->Next;
	}
	current->Next = temp->Next;
}
void display(Node* List) {
	for (Node* p = List->Next; p; p = p->Next)
		cout << p->value << " ";
	cout << endl;
}
int showmeposvalue(Node* List,int pos) {
	Node* position = List;
	for (int i = 0; i <= pos - 1; i++)
		position = position->Next;
	return position->value;
}
void insert_front(Node* List) {
	Node* temp = (Node*)malloc(sizeof(Node));
	cout << "Please input new node's Value:";
	cin >> temp->value;
	temp->Next = List->Next;
	List->Next = temp;
}
void insert_back(Node* List) {
	Node* pos = NULL;
	for (Node* p = List->Next; p; p = p->Next) {
		pos = p;
	};
	Node* temp = (Node*)malloc(sizeof(Node));
	cout << "Please input new node's Value:";
	cin >> temp->value;
	pos->Next = temp;
	temp->Next = NULL;
}
void deletevalue(Node* List) {
	int target;
	cout << "Please input your target:";
	cin >> target;
	Node* current = List;
	Node* temp = List->Next;
	for (Node* p = List->Next; p; p = p->Next) {
		if (p->value != target) {
			current = current->Next;
			temp = temp->Next;
		}
		else {
			temp = temp->Next;
			current->Next = temp;
			current = current->Next;
		}
	}
	display(List);
}

解析: 

1.void deletepos(Node*List,int pos) 删除第 pos 项的节点

void deletepos(Node* List, int pos) {
	Node* current = List;
	Node* temp = List->Next;
	for (int i = 0; i <= pos - 2; i++) {
		current = current->Next;
		temp = temp->Next;
	}
	current->Next = temp->Next;
}

此方法 适用于有头节点的链表,初始化 current 为头节点,temp为头节点.next 即实际链表的第一项,通过循环来移动两个指针,因为是用 temp 来记录第pos项的地址,又temp初始值为List.Next,所以循环条件为 i <= pos - 2 而不是 pos -1.得到了第 pos 项的地址后,将 pos 项 前一节点current所指向的节点变为temp.Next 操作为 current.Next=temp.Next 即可.

2.void display(Node*List)  Talk is shit,show me code 

void display(Node* List) {
	for (Node* p = List->Next; p; p = p->Next)
		cout << p->value << " ";
	cout << endl;
}

这里仅需解释循环条件 for( Node*p=List.Next,p,p=p.Next)

首先定义一个结构体指针 p 指向链表头节点之后,即链表的第一项,循环条件是 p,p是啥呢 先不看条件,先看循环结束后的操作 p = p.Next,很容易理解 此操作是将 p 的指向下移,即遍历所有链表指针,再回头看循环条件,当循环到p = NULL,即循环到尾节点之后的 NULL 时退出循环,因为这时所有的链表元素已经被遍历结束了.循环体中只需要输出所有遍历的节点的value值即可.

3.int showmeposvalue(Node* List, int pos) 显示第 pos 项的 value 值

int showmeposvalue(Node* List, int pos) {
	Node* position = List;
	for (int i = 0; i <= pos - 1; i++)
		position = position->Next;
	return position->value;
}

遍历到第 pos 个节点输出其 value 值即可 

4.void insert_front(Node* List) 在链表前插入一个节点

void insert_front(Node* List) {
	Node* temp = (Node*)malloc(sizeof(Node));
	cout << "Please input new node's Value:";
	cin >> temp->value;
	temp->Next = List->Next;
	List->Next = temp;
}

这里的插入分两种情况,情况一对于没有 头节点 的链表来说,直接创建一个新的节点 赋值后指向链表的第一项即可,情况二是有 头节点 的链表 这里的增加就不是简单的在整个链表的最前方增加节点了,而是创建一个节点 先去指向链表的第一项 ,再将头节点指向这个新的节点,至此形成新的链表.

5.void insert_back(Node* List) 在链表后插入一个节点

void insert_back(Node* List) {
	Node* pos = NULL;
	for (Node* p = List->Next; p; p = p->Next) {
		pos = p;
	};
	Node* temp = (Node*)malloc(sizeof(Node));
	cout << "Please input new node's Value:";
	cin >> temp->value;
	pos->Next = temp;
	temp->Next = NULL;
}

这里的添加 需要通过循环来找到链表的尾节点,再创建新节点并赋值后,将尾节点指向新节点 .

6.void deletevalue(Node* List) 删除链表内数值为value的节点

void deletevalue(Node* List) {
	int target;
	cout << "Please input your target:";
	cin >> target;
	Node* current = List;
	Node* temp = List->Next;
	for (Node* p = List->Next; p; p = p->Next) {
		if (p->value != target) {
			current = current->Next;
			temp = temp->Next;
		}
		else {
			temp = temp->Next;
			current->Next = temp;
			current = current->Next;
		}
	}
	display(List);
}

这个。我解释不了 因为不知道为啥我写的代码只能删除一次该 value 的节点,哈哈

5.22 >> 5.23 24:00

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值