链表的操作及应用

实现带头节点单链表的插入、查找以及删除操作

本关任务:要求针对链接存储方式实现的顺序表完成数据插入操作函数,以实现线性表数据插入功能。

针对链表数据,我们定义如下 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 **********/
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小狗碎碎念

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值