链表的创建及对其操作-复习

这篇博客详细介绍了如何在C语言中操作链表,包括单链表的头插法和尾插法,以及头插法下的删除和改值操作,尾插法的查找和插入操作。同时,博主分享了如何在递增有序链表中插入元素保持升序,以及使用C++合并两个升序链表的技巧,特别强调了哨兵节点的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、C-单链表-头插/尾插法-模板

#include "stdio.h"
#include "stdlib.h"
typedef struct List {
	int data; //数据域
	struct List *next; //指针域
} List;
 
void TailCreatList(List *L) //尾插法建立链表👈
{
	List *s, *r;//s用来指向新生成的节点。r始终指向L的终端节点。
	r = L; //r指向了头节点,此时的头节点是终端节点。
	for (int i = 0; i < 10; i++) {
		s = (struct List*) malloc(sizeof(struct List));//s指向新申请的节点
		s->data = i; //用新节点的数据域来接受i
		r->next = s; //用r来接纳新节点
		r = s; //r指向终端节点
	}
	r->next = NULL; //元素已经全部装入链表L中
	//L的终端节点指针域为NULL,L建立完成
 
}
 
void HeadCreatList(List *L) //头插法建立链表👈
{
	List *s;                          //不用像尾插法一样生成一个终端节点。
	L->next = NULL;
	for (int i = 0; i < 10; i++) {
		s = (struct List*) malloc(sizeof(struct List));
		s->data = i;
		s->next = L->next; //将L指向的地址赋值给S;//头插法与尾插法的不同之处主要在此,
						   //s所指的新节点的指针域next指向L中的开始节点
		L->next = s;       //头指针的指针域next指向s节点,使得s成为开始节点。
	}
}
 
void DisPlay(List *L) {    //打印节点
	List *p = L->next;
	while (p != NULL) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}
int main() {
	List *L1, *L2;
	L1 = (struct List*) malloc(sizeof(struct List));
	L2 = (struct List*) malloc(sizeof(struct List));
	HeadCreatList(L1);
	DisPlay(L1);
	TailCreatList(L2);
	DisPlay(L2);
}

原文链接


二、头插-删除操作-例题

在这里插入图片描述
题目清晰易懂,直接写:

#include <stdio.h>
#include <stdlib.h>
int cnt, x;//cnt记录节点个数,x用于data输入
//结构体节点,typedef可以使新定义结构体指针时省略关键字struct
typedef struct node
{
    int data;
    struct node *next;
} node;
void HeadCreatList(node *head)//传入头指针
{
    node *p;
    head->next = NULL;
    while (1)
    {
        scanf("%d", &x);
        if (x >= 0)
        {   //标准操作
            cnt++;
            p = (struct node *)malloc(sizeof(struct node));
            p->data = x;
            p->next = head->next;
            head->next = p;
        }
        else
        {
            break;//跳出
        }
    }
}
int main()
{
    struct node *head;//定义头指针
    head = (struct node *)malloc(sizeof(struct node));//这里需要给头指针开辟空间,有个地址
    HeadCreatList(head);//传入
    int del, pt = 0;//del为要删除的第del数,pt在输出的while中表示“当前节点排名”
    scanf("%d", &del);
    if (del == -1)
        del = cnt;//题目要求
    if (del > cnt)
        printf("Node not found!\n");//题目要求
    while (head->next != NULL)//注意头插与尾插的区别
    {
        pt++;
        if (pt == del) //逻辑删除,不输出即可
        {
            head = head->next; //这里要记得向后移动指针!
            continue;
        }
        else
            printf("%d ", head->next->data);//头插发head是没有的data的,data存储在head指向的结构体指针(head->next)中(head->next->data)
        head = head->next;//指针后移
    }
    //system("pause");
    return 0;
}

三、头插-改值操作-例题

在这里插入图片描述
其实这和上面那个几乎一模一样,输出部分改一下就行了

while (head->next != NULL)
    {
        pt++;
        if (pt == del)
            head->next->data=val;
        printf("%d ", head->next->data);
        head = head->next;
    }

可是为什么不直接输出呢,反正也不知道你改了没有/滑稽

while (head->next != NULL)
    {
        pt++;
        if (pt == del)
            printf("%d ",val);
        else
            printf("%d ", head->next->data);
        head = head->next;
    }

四、尾插-查找操作-例题

在这里插入图片描述
这些题都差不多的……

#include <stdio.h>
#include <stdlib.h>
//尾插链表
struct node
{
	int data, rank;//值,位置
	struct node *next;
};
int main()
{
	int n;
	while (~scanf("%d", &n))
	{
		//尾插基操
		int cnt = 0;
		struct node *head, *p1, *p2;
		head = NULL;
		p1 = p2 = (struct node *)malloc(sizeof(struct node));
		while (1)
		{
			cnt++;
			if (cnt == n + 1)//跳出
				break;
			p1->rank = cnt;//记录位置
			scanf("%d", &p1->data);
			(cnt == 1) ? (head = p1) : (p2->next = p1);
			p2 = p1;
			p1 = (struct node *)malloc(sizeof(struct node));
		}
		int find;//要找的值
		scanf("%d", &find);
		p2->next = NULL;
		int f = 0;//标志变量
		while (head != NULL)//这就是尾插与头插输出的不同,这里直接是head
		{
			if (head->data == find)//找到了
			{
				printf("%d %d\n", head->rank, head->data);
				f = 1;//改变状态
				break;
			}
			head = head->next;
		}
		if (f == 0)
			printf("0\n");
	}
	return 0;
}

五、尾插-插入操作-例题

这个也挺简单的,就新定义一个结构体指针,赋值后在要插入的位置改下连接方式即可

①在递增有序链表中插入一个值并使其仍然保持有序
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
int n, x;
typedef struct node
{
    int data;
    struct node *next;
} node;
node *head, *tail, *p, *newnode;
void TailCreate(int x)//尾插创建链表
{
    tail->next = (struct node *)malloc(sizeof(struct node));
    tail = tail->next;
    tail->data = x;
    tail->next = NULL;
}
void insert(int x)//插入操作
{
    p = (struct node *)malloc(sizeof(struct node));
    p = head;
    p->data = -1;//将表头(第0号节点)赋值-1以便于当x小于第一个节点时的插入操作
    while (p != NULL)
    {
        if (x < (p->next->data) && x > (p->data))//x小于前一个且大于后一个
        {
            newnode = (struct node *)malloc(sizeof(struct node));
            newnode->data = x;
            newnode->next = p->next;
            p->next = newnode;
            break;
        }
        p = p->next;
    }
}
int main()
{
    while (~scanf("%d", &n))
    {
        head = tail = (struct node *)malloc(sizeof(struct node));
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &x);
            TailCreate(x);
        }
        scanf("%d", &x);
        insert(x);
        head = head->next;//从0号节点移动到1号节点
        while (head != NULL)
        {
            printf("%d  ", head->data);//注意这题“间隔两个空格”
            head = head->next;
        }
        printf("\n");
    }
    //system("pause");
    return 0;
}

②无序输入,建立有序递增链表
在这里插入图片描述
其实看见这题我第一想法是用一个数组把输入先存下排序,再套上题代码就好了呀/滑稽
正儿八经的代码:

#include <stdio.h>
#include <stdlib.h>
int n, x;
typedef struct node
{
    int data;
    struct node *next;
} node;
node *head, *p, *newnode;
void insert(int x)//有序插入
{
    p = head;//每次进入函数使p从表头开始往后走
    while (p != NULL)//当p还指向链表中的节点
    {
        if (p->next == NULL)//如果p已经走到表尾(即下一个为NULL),x还未插入,就把x放在表尾
        {
            p->next = (struct node *)malloc(sizeof(struct node));
            p = p->next;
            p->data = x;
            p->next = NULL;//NULL后移
        }
        else
        {
            if (x > p->data && x < p->next->data)//按升序插入
            {
                newnode = (struct node *)malloc(sizeof(struct node));
                newnode->data = x;
                newnode->next = p->next;//连接前后节点
                p->next = newnode;
                break;
            }
        }
        p = p->next;//后移p
    }
}
int main()
{
    while (~scanf("%d", &n))
    {
        head = (struct node *)malloc(sizeof(struct node));
        head->data = -1;//表头第0个节点赋值-1,方便下x<第1个节点的判断
        head->next = NULL;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &x);
            insert(x);
        }
        head = head->next;//跳过表头(第0个节点)
        while (head != NULL)//输出
        {
            printf("%d  ", head->data);
            head = head->next;
        }
        printf("\n");
    }
    //system("pause");
    return 0;
}

六、合并升序链表,并保持升序

主要是强调关于c++里申请哨兵节点的方法:
ListNode *head = new ListNode(0)

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        if(!pHead2) return pHead1;
        if(!pHead1) return pHead2;
        ListNode *head=new ListNode(0); //这里切勿直接head=nullptr,混淆指针与对象
        ListNode *ptr=head;
        while(pHead1 && pHead2)
        {
            if(pHead1->val < pHead2->val) ptr->next=pHead1,pHead1=pHead1->next;
            else ptr->next=pHead2,pHead2=pHead2->next;
            ptr=ptr->next;
        }
        while(pHead1) ptr->next=pHead1,pHead1=pHead1->next,ptr=ptr->next;
        while(pHead2) ptr->next=pHead2,pHead2=pHead2->next,ptr=ptr->next;
        return head->next;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值