链表2021.1.8

本文介绍了链表的基本概念,包括链表的特点和初始化方法。通过实例展示了如何建立和输出链表,以及如何在链表中动态插入和删除结点。同时,详细阐述了链表的遍历操作。这些内容涵盖了链表操作的核心知识点,对于理解和操作链表非常有帮助。
摘要由CSDN通过智能技术生成

一,链表的认识

链表初始化的作用 :

生成链表头指针,以便后续函数的调用操作,在没有任何输入的情况下,我们首先定义一个头指针来保存即将创建的链表
在这里插入图片描述

链表是一种常见的重要的数据的存储结构

特点:

1结点地址不是连续的
2用上一个节点中的地址才能找到下一结点

链表的初始化:

用指针的结构体来实现

struct Node
{
	char data;				//用来存储数据
	struct Node *next;		//用来保存地址,寻找结点
};
struct Node *head			//定义一个链表头指针

二, 建立并输出一个如图所示的简单的链表在这里插入图片描述

#include <stdio.h>
struct student
{
	int num;
	float score;
	struct student *next;
};
int main()
{
	struct student a, b, c,  *head, *p;//a b c 为三个结点 *head为头指针 
	//将各个结点赋值
	//将结点连起来
	//将链表输出
	return 0}

1,将各结点赋值

a.num = ?;
a.score = ?;
b.num = ?;
b.score = ?;
c.num = ?;
c.score = ?;

2,将各个结点连起来

head = &a;
a.next = &b;
b.next = &c;
c.next = NULL;

3,输出个链表

p = head;
do
{
	printf("%d %.1f\n",&p->score,&p->num);
	p=p->next;
}while(P!=NULL);

三,链表中结点的插入和删除

1,动态分配和创建内存

在这里插入图片描述

#include <stdio.h>
struct student
{
	char num;
	float score;
	struct student *next;
};
int main()
{
	struct student *p;
	p = malloc(sizeof(struct student));//动态分配内存
	p->num = 31001;
	p->score = 89.5;
	printf("%d %.1f",&p->num,&p->score);
	free(p);//撤销内存
	return 0}

2,遍历链表(访问链表内的值并输出)

typedef struct NODE
{
	int data;
	struct NODE *next;
}Node;
void traverse(Node *h)
{
	Node *p;   
	p=h;  						//P指向头节点
	while(P->next = NULL)		//遍历标志
	{
		printf("%d",p->data);   //访问节点
		p=p->next;				//指向下一结点
	}
	printf("\n");
	return 0;
}

3,创建一个链表

在这里插入图片描述P是媒介
传递头指针给h,传递结点给last
last 是p新建的结点(新结点或下一个结点)

#include <stdio.h>
#include <malloc.h>

void traverse(Node *h)
Node *creatLinkList(int n)

typedef struct NODE
{
	int data;
	struct NODE *next;
}Node;

Node *creatLinkList(int n)
{
	Node *h = NUll,*p,*last;
	int i;
	int d;
	for(i=0;i<n;i++)
	{
		scanf("%d",&d);//用于给第一个头指针赋值
		p=(Node*)malloc(sizeof(Node));
		p->data =d;
		p->next = NULL;
		if(h == NULL)
		{
			h=p;
		}
		else
			last->next = p;
		last = p;
	}
	return h;//保存头结点
}

int main()
{
	Node *head;
	head = creatLinkList(5);//实参为5传递给形参n  让其循环5次 建立五个结点
	traverse(head);
	return 0;
}

void traverse(Node *h)//此h是形参  实参为head 并非creatLinkList中h
{
	Node *p;
	p = h;
	while(p!=NULL)
	{
		printf("%-5d",p->data);
		p=p-next;
    }
    printf(""\n);
    return;
}

4,在链表中插入一个结点

目的:
在这里插入图片描述过程:
在这里插入图片描述注意顺序不能发生改变

插入结点的应用-建立有序列表

例:将如图结点按顺序排列
在这里插入图片描述

    #include <stdio.h>
    #include <malloc.h>
    typedef struct NODE
    {
        int data;
        struct NODE *next;
    } Node;
    Node *insertNode(Node *h, int b);
    void traverse(Node *h);
     
     
    int main( )
    {
        int b[]= {67, 25, 78, 99, 87},i;
        Node *head=NULL;
        for(i=0; i<5; i++)
            head=insertNode(head, b[i]);
        traverse(head);
        return 0;
    }
    Node *insertNode(Node *h, int b)
    {
        Node *q1=h,*q2,*p;
        p=(Node*)malloc(sizeof(Node));  /*生成新结点*/
        p->data=b;
        if(h==NULL)   /*当前链表为空,p作为首结点*/
        {
            h=p;     /*头结点就是p,将p赋值给h*/
            p->next=NULL;  /*p的指针域赋值为空,表示尚无下一个结点*/
        }
        else if(p->data<h->data) /*要插入的元素值小于首结点元素,插入结点作为首结点*/
        {
            h=p;  /*将头结点h赋值为p*/
            p->next=q1; /*p的下一个结点是原先的首结点(见q1的初始化,其值为h)*/
        }
        else  /*在中间找到插入p的位置,将其插入*/
        {
            /*先找到合适的位置,q1的初值是h,即从头结点开始考察*/
            while((q1!=NULL&&p->data>=q1->data))
            {
                q2=q1;         /*q2记录q1的值*/
                q1=q1->next;   /*q1继续向后试探,直到a1*/
            }
            /*将新结点p插在q2后*/
            p->next=q2->next;  /*p的下一个结点为当前q2的下一结点,即p1*/
            q2->next=p;    /*q2的下一个结点y变为p,不再是q1*/
        }
        return h;
    }
     
     
    void traverse(Node *h)
    {
        Node *p;
        p = h;  /*p指向头结点*/
        while(p!=NULL)
        {
            printf("%-5d", p->data);  /*“访问”结点,此处用最简单的操作:读取输出*/
            p = p->next; /*p指向下一个结点,继续处理*/
        }
        printf("\n");
        return;
    }

5,在链表中删除结点

目的:
在这里插入图片描述
过程:
在这里插入图片描述

删除结点应用-在有序表中删除
#include <stdio.h>
#include <malloc.h>
typedef struct NODE
{
    int data;
    struct NODE *next;
} Node;
Node *insertNode(Node *h, int b);
Node *deleteNode(Node *h, int b);
void traverse(Node *h);
 
 
int main( )
{
    int b[]= {67, 25, 78, 99, 87},i;
    Node *head=NULL;
    for(i=0; i<5; i++)
        head=insertNode(head, b[i]);
    traverse(head);
    head=deleteNode(head, 43);
    traverse(head);
    head=deleteNode(head, 78);
    traverse(head);
    return 0;
}
Node *insertNode(Node *h, int b)
{
    Node *q1=h,*q2,*p;
    p=(Node*)malloc(sizeof(Node));  /*生成新结点*/
    p->data=b;
    if(h==NULL)   /*当前链表为空,p作为首结点*/
    {
        h=p;     /*头结点就是p,将p赋值给h*/
        p->next=NULL;  /*p的指针域赋值为空,表示尚无下一个结点*/
    }
    else if(p->data<h->data) /*要插入的元素值小于首结点元素,插入结点作为首结点*/
    {
        h=p;  /*将头结点h赋值为p*/
        p->next=q1; /*p的下一个结点是原先的首结点(见q1的初始化,其值为h)*/
    }
    else  /*在中间找到插入p的位置,将其插入*/
    {
        /*先找到合适的位置,q1的初值是h,即从头结点开始考察*/
        while((q1!=NULL&&p->data>=q1->data))
        {
            q2=q1;         /*q2记录q1的值*/
            q1=q1->next;   /*q1继续向后试探,直到a1*/
        }
        /*将新结点p插在q2后*/
        p->next=q2->next;  /*p的下一个结点为当前q2的下一结点,即p1*/
        q2->next=p;    /*q2的下一个结点y变为p,不再是q1*/
    }
    return h;
}
 
 
Node *deleteNode(Node *h, int b)
{
    Node *p, *q;
    p=h;   /*p首先指向头结点*/
    if(h==NULL)  /*链表为空时不能删除*/
        printf("List is null, delete fail.\n");
    else
    {
        /*首先找到要删除的结点*/
        while(b!=p->data&&p->next!=NULL)
        {
            q=p;    /*q记录p的值*/
            p=p->next;   /*p接着指向下一个结点,q一直保持是p的上一个结点*/
        }
        if(b==p->data)   /*要删除的结点p在链表中存在*/
        {
            if(p==h) /*要删除的结点就是头结点时,令h指向p的下一个结点即可*/
                h = p->next;
            else   /*否则,删除q的下一个结点p*/
                q->next = p->next;
            free(p);  /*释放p结点*/
        }
        else
            printf("%d not found, delete fail.\n", b);
    }
    return h;
}
 
 
void traverse(Node *h)
{
    Node *p;
    p = h;  /*p指向头结点*/
    while(p!=NULL)
    {
        printf("%-5d", p->data);  /*“访问”结点,此处用最简单的操作:读取输出*/
        p = p->next; /*p指向下一个结点,继续处理*/
    }
    printf("\n");
    return;
}

本文是听了贺利坚老师的从语言设计所总结的笔记并未验证程序,如果给大家造成麻烦请联系更改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值