数据结构—链表元素的删除和插入

链表相对于线性表的优点就在于插入和删除十分方便。
那么我用一个有意思的比喻来描述一下这个过程。

插入:

小红和小琴是好闺蜜,她们天天都拉着手(找男的比喻不大好啊,23333)
咳咳,就是这样(图中蓝色上衣的是小红,绿色裙子的是小琴)
这里写图片描述
小红的手和小琴的手拉着一起

之后有一个女生名字叫小美也想加入她们,和她们成为好闺蜜,那么就成了这样了 →_→
(我不是故意的)
这里写图片描述

这样小红的手和小琴的手就不拉在一起了,反而小红的手和小美的左手拉在一起,小美的右手与小琴的手拉在一起了。(这里的左右手是我们的视角看到的左右手)

现在把小红、小琴、小美各作为一个节点即节点a,节点b,节点k。
原来的情形是小红和小琴的手天天拉着:
a->next = b;
那么之后呢小美插进两人之间:
k->next = a->next; //小美的右手牵着曾经小红牵着的小琴
a->next = k; //小红牵着小美的左手

void Push_L(LinkList &L, int data, int i)
{
    Node *p = L;
    int j = 1;
    while(p&&j<i)
    {
        p=p->next;
        ++j;
    }
    Node *q = (LinkList)malloc(sizeof(Node));
    q->data = data;
    q->next = p->next;
    p->next = q;
} 
删除:

因为小红和小琴两人嫉妒小美的貌美,就不接受她继续在她们两者之间了,那么就要把小美“踢”出去。
a->next = k->next;//小红继续和小琴牵着手
free(k); //小美成了独立人2333

void Delete_L(LinkList &L,int i)
{
    LinkList p = L;
    if(i<0)
    printf("INFEASIBLE");
    int j = 1;
    while(p&&j<i)
    {
        p=p->next;
        ++j;
    }
    Node *q = p->next;
    p->next = p->next->next;
    free(q);
}

实现的整个代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
    int data;
    struct node *next;
}Node,*LinkList;

/*创建一个新链表*/
void CreatList_L(LinkList &L,int n)
{
    int a; 
    L = (LinkList)malloc(sizeof(Node));
    L->next = NULL;//建立一个带头结点的单链表 
    Node *q = L; 
    for(int i=0;i<n;i++)
    {
        Node *p = (LinkList)malloc(sizeof(Node));
        scanf("%d",&a);
        p->data = a;
        q->next = p;
        p->next=NULL;
        q = q->next;
    }
}

/*在链表的第i处插入一个元素*/
void Push_L(LinkList &L, int data, int i)
{
    Node *p = L;
    int j = 1;
    while(p&&j<i)
    {
        p=p->next;
        ++j;
    }
    Node *q = (LinkList)malloc(sizeof(Node));
    q->data = data;
    q->next = p->next;
    p->next = q;
} 

/*删除第i个元素*/ 
void Delete_L(LinkList &L,int i)
{
    Node *p = L;
    if(i<0)
    printf("INFEASIBLE");
    int j = 1;
    while(p&&j<i)
    {
        p=p->next;
        ++j;
    }
    Node *q = p->next;
    p->next = p->next->next;
    free(q);
}
void Traverse_L(LinkList &L)
{
    LinkList p = L->next;
    while(p!=NULL){
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
}//正序遍历整个链表 

int main()
{
    LinkList L;
    int n;
    printf("输入要创建的链表中的元素个数:\n");
    scanf("%d",&n);
    printf("输入%d个元素:\n",n);
    CreatList_L(L,n);
    printf("遍历整个链表\n");
    Traverse_L(L);

    int push_data,push_i;
    printf("输入你想要插入的元素和它的插入位置:\n");
    {
        scanf("%d%d",&push_data,&push_i);
    }
    Push_L(L, push_data, push_i);
    printf("插入后的链表遍历为:\n");
    Traverse_L(L);

    int del_i;
    printf("输入要删除链表中的第几个元素:\n");
    scanf("%d", &del_i);
    Delete_L(L, del_i);

    printf("删除后的链表遍历为:\n");
    Traverse_L(L);
    return 0;    
}

效果图:

这里写图片描述


———————————————分割线————————————————–

今天数据结构上机实验要实现字符串链表,改一下数据类型就行,新增头插法:
(Ps:老师竟然让手抄实验报告,我内心是拒绝的,让我们照着敲挺没意义的,想学的人照样会学,不学的人你给他代码,照着打一遍后就忘了,何必呢?我觉得最好的学习方式就是先自己思考,实在不会再提供提示或参考,这样效果是最佳的!!)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct node{
    char data[10];
    struct node *next;
}Node,*LinkList;

/*创建一个新链表(尾插法)*/
void CreatList_tail(LinkList &L)
{
    L = (LinkList)malloc(sizeof(Node));
    L->next = NULL;//建立一个带头结点的单链表 
    Node *q = L; 
    while(1)
    {
        char ch[10];
        printf("Input # to end ");
        printf("Please input Node_data:");
        Node *p = (LinkList)malloc(sizeof(Node));

        scanf("%s", ch);
        if(strcmp(ch, "#") == 0) break;
        strcpy(p->data, ch);
        q->next = p;
        p->next = NULL;
        q = q->next;
    }
    return;
}

/*头插法*/ 
void CreatList_head(LinkList &L)
{
    L = (LinkList)malloc(sizeof(Node));
    L->next = NULL;//建立一个带头结点的单链表 
    while(1)
    {
        char ch[10];
        printf("Input # to end ");
        printf("Please input Node_data:");
        Node *p = (LinkList)malloc(sizeof(Node));

        scanf("%s", ch);
        if(strcmp(ch, "#") == 0) break;
        strcpy(L->data, ch);
        p->next = L;
        L = p;
    }
    return;
}

/*按值查找结点,找到则返回该结点的位置,否则返回NULL*/
Node *LocateNode(LinkList L, char *ch)
{
    Node *p = L;
    while(p!=NULL && strcmp(p->data, ch) != 0)
    {
        p = p->next;
    } 
     return p;
}

/*在链表的第i处插入一个元素*/
void Push_L(LinkList &L, char *ch, int i)
{
    Node *p = L;
    int j = 0;
    while(p&&j<i)
    {
        p=p->next;
        ++j;
    }
    Node *q = (LinkList)malloc(sizeof(Node));
    strcpy(q->data, ch);
    q->next = p->next;
    p->next = q;
} 

/*删除元素*/ 
void Delete_L(LinkList &L, char *ch)
{
    Node *p = L;
    while(strcmp(p->next->data, ch)!=0)
    {
        p=p->next;
    }
    Node *q = p->next;
    p->next = p->next->next;
    free(q);
}

void Traverse_L(LinkList &L)
{
    LinkList p = L->next;
    while(p!=NULL){
        printf("%s, ",p->data);
        p = p->next;
    }
    printf("\n");
}//正序遍历整个链表 

//void Inverted_L(LinkList &L1,LinkList &L2)
//{
//    Node *p1 = L1->next;
//    L2 = (LinkList)malloc(sizeof(Node));
//    L2->next=NULL;
//    while(p1!=NULL)
//    {
//        Node *p2 = (LinkList)malloc(sizeof(Node));
//        strcpy(p2->data, p1->data);
//        p2->next=L2->next;
//        L2->next=p2;
//        p1=p1->next;
//    }
//}

int main()
{
    LinkList L1;
    char num[5];
    char ch[10];
    CreatList_head(L1);
    Traverse_L(L1);

    printf("Delete node (y/n):");
    scanf("%s",num);
    if(strcmp(num, "y")==0 || strcmp(num, "Y")==0)
    {
        printf("Please input Delete_data:");
        scanf("%s",ch);
        Delete_L(L1, ch);       
        Traverse_L(L1);
    }

    printf("Insert node (y/n):");
    scanf("%s", num);
    if(strcmp(num, "y")==0 || strcmp(num, "y")==0)
    {
        char push_data[10];
        int push_i;
        printf("Please input a New Node_data:");
        scanf("%s",push_data);
        printf("postion :");
        scanf("%d",&push_i);
        Push_L(L1, push_data, push_i);
        Traverse_L(L1);
    }
    return 0;    
}

这里写图片描述

  • 16
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值