【数据结构】单链表查找和删除:多位序查找和删除

查找

要求

输入要查找的值x,调用按值查找单链表函数,输出它的位序(可能多个)

思路

基础查找函数:

Status QueryNode(LinkList L,ElemType x)
{
LinkList p;int i=0;
p=L->next;
while(p!=NULL)
{
if(p->data=x)
{
i++;
printf("元素%d在链表第%d位\n",x,i);
return OK;
}
p=p->next;
}
return ERROR;
}

在这个函数中,只要找到一个x值,立刻打印其位序并返回OK,退出函数。现在我们既要返回函数的ERROR或OK,又要打印出所有的i值,不妨先把所有的i值存储起来,循环结束后统一打印,打印结束后返回OK。

那么,ERROR该何时返回呢?由于i值个数不确定,考虑用链表存储i值,参考尾插法。若没有i值,则该链表为空表。在循环结束后判断其是否为空表,是则返回ERROR,否则打印并返回OK。

然而,在编译器中,若不在函数外对B初始化(包括data域和next域),会报错。这样一来,就不存在空表B了。易知i不可能为小于等于0的数,那么可对B进行如下初始化:

LinkList B; 
B = (LinkList)malloc(sizeof(LNode));
 B->data = 0; 
B->next = NULL;

这样一来,就解决了存储位序值、判空返回正误、未初始化报错的问题。

查找函数:

Status QueryNode(LinkList L, ElemType x, LinkList B)//查找
{
    LinkList p;
    /*B的尾插指针*/LinkList s, r;
    /*B的尾插操作*/B = (LinkList)malloc(sizeof(LNode)); r = B;  
    p = L->next;
    int i = 1;
    while (p != NULL)
    {
        if (p->data == x)
        {
            /*B的尾插操作*/s = (LinkList)malloc(sizeof(LNode));
            s->data = i;
            r->next = s;
            r = s;
        }
        p = p->next;
        i++;
    }
    /*B的尾插操作*/r->next = NULL;
    if (B->data == 0) return ERROR;
    printf("元素%d在如下位置:\n", x);
    DisplayLink(B);
    return OK;
}

代码及运行结果

#include <stdio.h>
#include <stdlib.h>
constexpr auto ERROR = 0;
constexpr auto OK = 1;
typedef int ElemType;
typedef int Status;
typedef struct Node {
    ElemType data;
    struct Node* next;
}LNode, * LinkList;
void CreateList(LinkList& L, int n)//尾插法
{
    LinkList  p, q; int i;
    L = (LinkList)malloc(sizeof(LNode));
    q = L;
    for (i = 0; i < n; ++i) {
        p = (LinkList)malloc(sizeof(LNode));
        scanf_s("%d", &p->data);
        q->next = p;
        q = p;
    }  
    q->next = NULL;
}
void DisplayLink(LinkList L)//输出
{
    LinkList p;
    p = L->next;
    while (p != NULL)
    {
        printf("%d\n", p->data);
        p = p->next;
    }
}
Status QueryNode(LinkList L, ElemType x, LinkList B)//查找
{
    LinkList p;
    /*B的尾插指针*/LinkList s, r;
    /*B的尾插操作*/B = (LinkList)malloc(sizeof(LNode)); r = B;  
    p = L->next;
    int i = 1;
    while (p != NULL)
    {
        if (p->data == x)
        {
            s = (LinkList)malloc(sizeof(LNode));
            s->data = i;
            r->next = s;
            r = s;
        }
        p = p->next;
        i++;
    }
    r->next = NULL;
    if (B->data == 0) return ERROR;
    printf("元素%d在如下位置:\n", x);
    DisplayLink(B);
    return OK;
}
int main(void)
{
    LinkList A; LinkList B; B = (LinkList)malloc(sizeof(LNode)); B->data = 0; B->next = NULL;
    int m;
    printf("您要创建几位的链表\n");
    scanf_s("%d", &m);
    printf("请输入%d个元素\n", m);
    CreateList(A, m);
    printf("您已创建链表如下:\n");
    DisplayLink(A);
    int x;
    printf("要查找的元素:\n");
    scanf_s("%d", &x);
    QueryNode(A, x, B);
    return 0;
}

删除

要求

输入要删除的值g,调用按值删除函数,输出更新后的链表。(可能多个)

思路

基本删除函数

Status DeletList(LinkList &L,int i,ElemType &e)//删除第i个结点
{
 LinkList p,q;//q指向第i个结点。循环结束时,p指向第i-1个结点
 p=L;//p存储头结点的地址
 int j=0;
 while(p->next&&j<i-1)
 {
  p=p->next;
  i++;
 }
 if(!p->next||j>i-1) return ERROR;
//*****************************
 q=p->next;
 p->next=q->next;//第i-1个结点的指针域指向第i+1个结点
//*****************************
 e=q->data;//用e存放q的数据域
 free(q);//释放第i个结点
 return OK; 
}

改进如下

Status ListDelete(LinkList &L, int x)//删除
{
    LinkList j, k; 
    k = L;//避免因k未初始化而报错
    j = L; 
    while (j->next!= NULL)
    {
        k = j->next;//每次循环都重新对k赋值
        if (k->data == x)
        {
            j->next = k->next;
            free(k);
        }    
        else j = j->next;
    }
    if (k==L) return ERROR;
    return OK;
}

图解

代码及运行结果

#include <stdio.h>
#include <stdlib.h>
constexpr auto ERROR = 0;
constexpr auto OK = 1;
typedef int ElemType;
typedef int Status;
typedef struct Node {
    ElemType data;
    struct Node* next;
}LNode, * LinkList;
void CreateList(LinkList& L, int n)//尾插法
{
    LinkList  p, q; int i;
    L = (LinkList)malloc(sizeof(LNode));
    q = L;
    for (i = 0; i < n; ++i) {
        p = (LinkList)malloc(sizeof(LNode));
        scanf_s("%d", &p->data);
        q->next = p;
        q = p;
    }  
    q->next = NULL;
}
void DisplayLink(LinkList L)//输出
{
    LinkList p;
    p = L->next;
    while (p != NULL)
    {
        printf("%d\n", p->data);
        p = p->next;
    }
}
Status ListDelete(LinkList &L, int x)//删除
{
    LinkList j, k; 
    k = L;//避免因k未初始化而报错
    j = L; 
    while (j->next!= NULL)
    {
        k = j->next;
        if (k->data == x)
        {
            j->next = k->next;
            free(k);
        }    
        else
        {
            j = j->next;
        }
    }
    if (k==L) return ERROR;
    return OK;
}
int main(void)
{
    LinkList A;
    int c,g;
    printf("要创建几位的链表\n");
    scanf_s("%d", &c);
    printf("输入表中元素\n");
    CreateList(A, c);
    printf("您已创建链表如下\n");
    DisplayLink(A);
    printf("要删除几\n");
    scanf_s("%d", &g);
    ListDelete(A, g);
    printf("更新链表如下:\n");
    DisplayLink(A);
    return 0;
}

运行结果如下:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值