实现带头节点单链表的插入、查找以及删除操作
本关任务:要求针对链接存储方式实现的顺序表完成数据插入操作函数,以实现线性表数据插入功能。
针对链表数据,我们定义如下 5 个基本操作:
创建空的带头结点单链表:创建一个链接存储的线性表,初始为空表。具体操作函数定义如下:
bool InitList(LinkList &L)
在带头节点单链表 L 中查找值为 X 的节点,如果找到返回该节点的地址,否则返回 NULL,具体操作函数定义如下:
LNode* Find( LinkList L, ElemType X )
将 X 插入在指针 P 指向的结点之前,返回 true。 P==NULL ,表示要插入的位置是表尾。如果参数 P 指向非法位置,则打印“Wrong Position for Insertion\n”,返回 false,具体操作函数定义如下:
bool Insert( LinkList &L, ElemType X, LNode* P )
将指针 P 所指向的元素删除并返回 true。若参数 P 指向非法位置,则打印“Wrong Position for Deletion\n”并返回 false,具体操作函数定义如下:
bool Delete( LinkList &L, LNode* P )
打印整个线性表: 每个结点元素值以逗号间隔,以换行符结束。具体操作函数定义如下:
void DispList(LinkList L)
#include<iostream>
using namespace std;
#define ERROR NULL
typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型
typedef struct LNode
{
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
bool InitList(LinkList &L);//初始化一个为空的带头结点单链表
LNode* Find( LinkList L, ElemType X ); //在带头节点单链表L中查找值为X的节点,如果找到返回该节点的地址,否则返回NULL
bool Insert( LinkList &L, ElemType X, LNode* P );
//将X插入在指针P指向的结点之前,返回true。 P==NULL ,表示要插入的位置是表尾。如果参数P指向非法位置,则打印“Wrong Position for Insertion\n”,返回false;
bool Delete( LinkList &L, LNode* P );
//将指针P所指向的元素删除并返回true。若参数P指向非法位置,则打印“Wrong Position for Deletion\n”并返回false。
void DispList(LinkList L); //顺序输出链表每个结点,每个结点元素值以空格符间隔,以换行符结束。
/*在带头节点单链表L中查找值为X的节点,如果找到返回该节点的地址,否则返回NULL */
LNode* Find( LinkList L, ElemType X )
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *p = L->next; // 从第一个节点开始
while (p != NULL) {
if (p->data == X) {
return p; // 找到节点
}
p = p->next; // 移动到下一个节点
}
return NULL; // 没有找到
/********** End **********/
}
/*将X插入在指针P指向的结点之前,返回true。 P==NULL ,表示要插入的位置是表尾。如果参数P指向非法位置,则打印“Wrong Position for Insertion\n”,返回false; */
bool Insert( LinkList &L, ElemType X, LNode* P )
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *N = new LNode; // 创造一个新链表
N->data = X; // 从这个数据开始查找
if (P == NULL) {
LNode *p = L;
while (p->next != NULL) { // 遍历至末尾
p = p->next;
}
p->next = N; // 连接新节点
N->next = NULL; // The new node should point to NULL
return true;
} else {
LNode *p = L; // Start from the head
while (p->next != P && p->next != NULL) { // Find the node before P
p = p->next;
}
if (p->next != P) { // P is invalid
cout << "Wrong Position for Insertion" << endl;
delete N; // Free the allocated node
return false;
}
N->next = p->next; // Link the new node to the next node
p->next = N; // Link the previous node to the new node
return true;
}
/********** End **********/
}
/*将指针P所指向的元素删除并返回true。若参数P指向非法位置,则打印“Wrong Position for Deletion\n”并返回false。*/
bool Delete( LinkList &L, LNode* P )
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
if (P == NULL || L->next == NULL) { // If P is NULL or the list is empty
cout << "Wrong Position for Deletion" << endl;
return false;
}
LNode *p = L; // Start from the head
while (p->next != NULL && p->next != P) { // Find the node before P
p = p->next;
}
if (p->next != P) { // P is invalid
cout << "Wrong Position for Deletion" << endl;
return false;
}
LNode *toDelete = p->next; // Node to delete
p->next = toDelete->next; // Bypass the node to delete
delete toDelete; // Free the memory
return true;
/********** End **********/
}
实现带头节点单链表指定位置插入、删除以及查找操作
本关任务:要求针对链接存储方式实现的线性表完成数据插入、删除以及查找操作,以实现线性表数据操作功能
针对链表数据,我们定义如下操作:
创建空的带头结点单链表:创建一个链接存储的线性表,初始为空表。具体操作函数定义如下:
bool InitList(LinkList &L)
将 X 插入在第 i 个位置,i≥1,返回 true。如果参数i指向非法位置(i<1 或者 i>n+1,其中 n 表示表中元素个数),则打印“Wrong Position for Insertion\n”,返回 false,具体操作函数定义如下:
bool ListInsert(LinkList &L, int i, ElemType X)
删除线性表中第 i 个位置的元素并返回 true。如果参数 i 指向非法位置(i<1 或者 i>n ,其中 n 表示表中元素个数),则打印“Wrong Position for Deletion\n”并返回 false,具体操作函数定义如下:
bool ListDelete(LinkList &L, int i)
打印整个线性表: 每个结点元素值以逗号间隔,以换行符结束。具体操作函数定义如下:
void DispList(LinkList L)
释放线性表节点:释放链表的结点,然后释放 Linklist 所指向的结构。具体操作函数定义如下:
void Free( LinkList &L)
编程要求
根据提示,在右侧编辑器代码文件中的 Begin-End 区间内补充代码,实现 step2/LinkList.h 中的 Find、Insert 以及 Delete 三个基本操作函数,具体要求如下:
ListFind 函数:在带头节点单链表 L 中查找值为 X 的节点,如果找到返回该节点的地址,否则返回 NULL。
ListInsert 函数:将 X 插入在第 i 个位置,i≥1,返回 true。如果参数 i 指向非法位置(i<1 或者 i>n+1,其中 n 表示表中元素个数),则打印“Wrong Position for Insertion\n”,返回 false。
ListDelete 函数:删除线性表中第 i 个位置的元素并返回 true。如果参数 i 指向非法位置(i<1 或者 i>n,其中 n 表示表中元素个数),则打印“Wrong Position for Deletion\n”并返回 false。
#include<iostream>
using namespace std;
#define ERROR NULL
typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型
typedef struct LNode
{
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
/* 创建空的带头结点单链表:创建一个链接存储的线性表,初始为空表。具体操作函数定义如下:*/
bool InitList(LinkList &L);
/* 将X插入在第i个位置,1≤i≤n+1,返回true。如果参数i指向非法位置(i<1或者i>n+1 ,其中n表示表中元素个数),
则打印“Wrong Position for Insertion\n”,返回false,具体操作函数定义如下: */
bool ListInsert(LinkList &L, int i, ElemType X);
/* 删除线性表中第i个位置的元素并返回true。如果参数i指向非法位置(i<1或者i>n ,其中n表示表中元素个数),
则打印“Wrong Position for Deletion\n”并返回false,具体操作函数定义如下:*/
bool ListDelete(LinkList &L, int i);
/*在带头节点单链表L中第i个结点,如果找到返回该节点的地址,否则返回NULL */
LNode* ListFind( LinkList L, int i );
/*顺序输出链表每个结点,每个结点元素值以逗号间隔,以换行符结束。 */
void DispList(LinkList L);
/*在带头节点单链表L中第i个结点,如果找到返回该节点的地址,否则返回NULL */
LNode* ListFind( LinkList L, int i )
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
if (i < 1) return ERROR; // i不合法
LNode* p = L->next; // 从头结点的下一个结点开始
int j = 1; // 计数器
while (p && j < i) {
p = p->next; // 移动到下一个节点
j++;
}
return (j == i) ? p : ERROR; // 如果找到了对应位置的节点,则返回该节点
/********** End **********/
}
/* 将X插入在第i个位置,i≥1,返回true。如果参数i指向非法位置(i<1或者i>n+1 ,其中n表示表中元素个数),
则打印“Wrong Position for Insertion\n”,返回false,具体操作函数定义如下: */
bool ListInsert(LinkList &L, int i, ElemType X)
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
if (i < 1) {
cout << "Wrong Position for Insertion\n";
return false; // 不合法的位置
}
LNode* p = L; // 从头结点开始
int j = 0; // 计数器
while (p && j < i - 1) { // 找到第i-1个位置
p = p->next;
j++;
}
if (!p) {
cout << "Wrong Position for Insertion\n";
return false; // 不合法的位置
}
// 创建新节点
LNode* newNode = new LNode;
newNode->data = X;
newNode->next = p->next; // 将新节点的next指向当前位置的next
p->next = newNode; // 将第i-1个节点的next指向新节点
return true;
/********** End **********/
}
/* 删除线性表中第i个位置的元素并返回true。如果参数i指向非法位置(i<1或者i>n ,其中n表示表中元素个数),
则打印“Wrong Position for Deletion\n”并返回false,具体操作函数定义如下:*/
bool ListDelete( LinkList &L, int i )
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
if (i < 1) {
cout << "Wrong Position for Deletion\n";
return false; // 不合法的位置
}
LNode* p = L; // 从头结点开始
int j = 0; // 计数器
while (p->next && j < i - 1) { // 找到第i-1个位置
p = p->next;
j++;
}
if (!p->next || j != i - 1) {
cout << "Wrong Position for Deletion\n";
return false; // 不合法的位置或节点不存在
}
LNode* toDelete = p->next; // 要删除的节点
p->next = toDelete->next; // 跳过要删除的节点
delete toDelete; // 释放内存
return true;
/********** End **********/
}
删除带头节点单链表 L 中所有值为 X 的结点。
本关任务:删除带头节点单链表 L 中所有值为 X 的结点。
#include <iostream>
using namespace std;
typedef int datatype;
typedef struct ListNode {
datatype data;
struct ListNode *next;
}LNode,*LinkList;
/*创建一个非空的带头节点单链表 */
void CreatbyQueue(LinkList &L);
/*//删除带头节点单链表L中所有值为X的结点。 */
void DelAllX(LinkList &L,datatype X);
/*顺序输出链表每个结点,每个结点元素值以空格符间隔,以换行符结束。 */
void DispList(LinkList L);
/*//删除带头节点单链表L中所有值为X的结点。 */
void DelAllX(LinkList &L,datatype X)
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *current = L->next; // 从头结点的下一个节点开始遍历
LNode *prev = L; // prev始终指向current的前一个节点
while (current != NULL) {
if (current->data == X) {
// 如果当前节点的数据等于X,删除当前节点
prev->next = current->next; // 跳过当前节点
delete current; // 释放当前节点的内存
current = prev->next; // 移动current到下一个节点
} else {
// 如果当前节点的数据不等于X,移动prev和current
prev = current;
current = current->next;
}
}
/********** End **********/
}
插入操作有序
本关任务:假设带头结点的单链表 L 是值的大小非降序排列的,请将值为 x 的结点插入到链表 L 中,并保持链表 L 的有序性。
#include<iostream>
using namespace std;
#define ERROR NULL
typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型
typedef struct LNode
{
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
/*创建一个非空的带头结点单链表 */
void CreatbyQueue(LinkList &L);
/*将值为x的结点插入到有序链表L中,并保持链表有序性。 */
void InsertOrder( LinkList &L, ElemType X);
/*顺序输出链表每个结点,每个结点元素值以空格符间隔,以换行符结束。 */
void DispList(LinkList L);
/*将值为x的结点插入到有序链表L中,并保持链表有序性。 */
void InsertOrder( LinkList &L, ElemType X)
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *current = L; // 从头结点开始
LNode *newNode = new LNode; // 创建新节点
newNode->data = X;
newNode->next = NULL;
// 寻找插入位置
while (current->next != NULL && current->next->data < X) {
current = current->next; // 移动到下一个节点
}
// 插入新节点
newNode->next = current->next;
current->next = newNode;
/********** End **********/
}