建立单链表

目录

链表的概念

链表的组成:

 基本概念:

链表的种类

建立一个静态链表

动态链表

如何动态的生成一个链表?

1.函数原型: void *malloc(unsigned size)

2.函数原型: void free(void*p)

3.几点注意:

特点:

建立单链表

关于单链表

建立单链表的主要步骤:

代码


链表的概念

链表是动态地进行存储分配的一种结构,链表中的数据在内存中不必连续存放,数据之间通过指针链接起来,相比于数组结构,链表的插入和删除操作比较方便。

如图,随机开辟5个空间,第一个空间称为链表的表头,它存放第二个空间的地址。剩下的每块空间分为数据域和指针域。数据域用来存放数据,指针域存放下一块空间的地址,从而将每块空间链接起来。最后一块空间称为链表的表尾,其指针域存放一个空指针,用于结束链表。

链表的组成:

  • 头指针:存放一个地址,该地址指向一个元素
  • 结点:用户需要的实际数据和链接节点的指针

 基本概念:

①链表指的是将若干个数据项按一定的规则连接起来的表。

②链表中的数据项称为结点。

③链表中每一个结点的数据类型都包含一个自引用结构

④自引用结构就是结构成员中包含一一个指针成员,该指针指向与自身同一个类型的结构。

因此:链表就是结构体变量与结构体变量连接在一起。(通过结 构体指针)

例如:

struct node
{
    int data;
    struct node*next;
};


struct student
{
    int num;
    char name[10];
    int age;
}
struct node
{
    struct node stu;
    struct node*next;
};

解析:链表中的结点是结构体类型的数据,每个结点的所有成员分为两部分,一部分用来存放数据(各种实际的信息),如编号、姓名和年龄等;另一部分存放指针,用来连接其它结点。

链表的种类

  1. 单向链表:每个结点除了一些数据成员外,只包含一个指针成员。单向链表通常有一个头指针(head),用于指向链表头。单向链表有一个尾结点,尾结点的指针成员存放的是空指针(NULL)。
  2. 循环链表:最后一个结点的指针指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链。
  3. 双向链表:结点除含有数据成员外,还有两个指针成员,一个指针成员存储直接后继结点地址;另一个指针成员存储直接前驱结点地址。

建立一个静态链表

struct node
{
  int data;
  struct node*next;  
};
int main()
{
    struct node n1={1,NULL};
    struct node n2={2,NULL};
    struct node n3={3,NULL};
    struct node*p;
    n1.next=&n2;
    n2.next=&n3;
    p=&n1;
    while(p!=NULL)
    {
        printf("%d\t",p->data);
        p=p->next;    
    }
    return 0;
}

此例用于说明链表的构成,静态链表作用不大,一般使用动态链表

动态链表

指动态的数据结构,可以将不连续的内存数据连接起来。用上malloc、free函数

如何动态的生成一个链表?

需要用到的几个函数和运算符:

malloc()和free()函数以及sizeof运算符的配合使用

(注: malloc()和free()函 数在头文件stdlib.h或alloc.h)。

1.函数原型: void *malloc(unsigned size)

功能:从内存分配-一个大小为size个字节的内存空间。.

◆若成功,返回新分配内存的首地址;若没有足够的内存分配,则返回NULL。

◆通常函数malice()通常和运算符sizeof一起使 用。

例如:

int * p;

p= (int *) malloc(20*sizeof(int)); / *分配20个整型数所需的内存空间* /

系统分配能存放20个整型数连续空间,p指向该存储空间的首地址。

例如:

struct student

{ int no;

int score;

struct student *next;

};

struct student*stu;

stu=malloc(sizeof(struct student));

2.函数原型: void free(void*p)

功能:释放由malloc函数所分配的内存块,无返回值。例如: free(stu);

作用:将stu所指的内存空间释放。

3.几点注意:

①结构类型占用的内存空间不一定是连续的,因此,应该用sizeof运算符来确定结构类型占用内存空间的大小。

②使用malloc()函数时,应对其返回值进行检测是否为NULL,以确保程序的正确。

③要及时地使用free()函数释放不再需要的内存空间,避免系统资源过早地用光。

④不要引用已经释放的内存空间。

特点:

1、链表中的每一个结点是在需要的时候建立的。

2、各结点在内存中的存储地址不一定是连续的,由系统自动分配的,即有可能是连续分配内存空间,也有可能是跳跃式的不连续分配内存空间。

建立单链表

关于单链表

单链表的建立链表:通过自引用结构的指针域,将各结点相互连接。关于链表的基本概念:

(1)链表的第一个结点称头指针或头结点,它指向链表在内存中的首地址,

(2)其后的结点是通过结点中的链节指针成员访问的。

(3)链表的最后一个结点称为尾节点。尾节点的指针域通常被设置成NULL。

(4)链表中的每一个结点是在需要的时候建立的。

(5)各结点在内存中的存储地址不一定是连续的,由系统自动分配的,即有可能是连续分配内存空间,也有可能是跳跃式的不连续分配内存空间。

建立单链表的主要步骤:

①定义单链表的数据结构(定义自引用结构)

②建立表头(建立一个空表)。

③创建一个结点

④插入一个结点(表头、表尾、指定位置插入)

⑤删除结点(指定删除)

⑥遍历链表(打印输出值)

代码

1、定义单链表的数据结构

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

 2、建立表头

struct Node* creatlist()
{
    struct Node* head = (struct Node*)malloc(sizeof(struct Node));
    head->next = NULL;
    return head;
}

3、创建一个结点

struct Node* creatnode(int data)
{
    struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
    newnode->data = data;
    newnode->next = NULL;
    return newnode;
}

 

4、插入一个结点(这里我们使用在表头插入的方法)

void InsertNode(struct Node* head, int data)
{
    struct Node* newnode = creatnode(data);
    newnode->next = head ->next;
    head->next = newnode;
}

head->next即图中newnode1的地址,将其赋给newnode2->next。再将head->next修改成newnode2的地址。这样就将新结点插入进去。这里特别注意顺序

 5、删除结点

void deleteNode(struct Node* head, int givedata)//head为表头,givedata为要删除的数据
{
    struct Node* giveNode = head->next;//giveNode为表头的下一个结点
    struct Node* frontgiven = head;
    if (giveNode == NULL)
    {
        printf("链表为空");
    }
    else
    {
        while (giveNode->data != givedata)//匹配数据域,不同则后移
        {
            frontgiven = giveNode;
            giveNode = giveNode->next;
            if (giveNode == NULL)
            {
                printf("找不到该数据");
                break;
            }
        }
        frontgiven->next = giveNode->next;//找到要删除的数据,将前一个结点的指针域指向下一个结点
        free(giveNode);
    }
}

6、遍历链表

void print(struct Node*head)
{
    struct Node* p=head->next;
    while (p)
    {
        printf("%d\t", p->data);
        p = p->next;
    }
}

 7、全部代码:


#include<stdio.h>
#include"stdlib.h"

struct Node {
	int data;
	struct Node* next;
};
struct Node* creatlist()
{
	struct Node* head = (struct Node*)malloc(sizeof(struct Node));
	head->next = NULL;
	return head;
}
struct Node* creatnode(int data)//创建一个结点
{
	struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
	newnode->data = data;
	newnode->next = NULL;
	return newnode;
}
void InsertNode(struct Node* head, int data)
{
	struct Node* newnode = creatnode(data);
	newnode->next = head ->next;
	head->next = newnode;
	
}
void print(struct Node*head)
{
	struct Node* p=head->next;
	while (p)
	{
		printf("%d\t", p->data);
		p = p->next;
	}
}

void deleteNode(struct Node* head, int givedata)
{
	struct Node* giveNode = head->next;
	struct Node* frontgiven = head;
	if (giveNode == NULL)
	{
		printf("链表为空");
	}
	else
	{
		while (giveNode->data != givedata)
		{
			frontgiven = giveNode;
			giveNode = giveNode->next;
			if (giveNode == NULL)
			{
				printf("找不到该数据");
				break;
			}
		}
		frontgiven->next = giveNode->next;
		free(giveNode);
	}
}

int main()
{
	//建立一个表头
	struct Node* list = creatlist();
	/*int xuehao;*/
	/*int flag = 1;*/
	
	//while (flag) {
	//	printf("请输入一个学号\n");
	//	scanf("%d", &xuehao);
	//	//在表头插入数据
	//	InsertNode(list, xuehao);
	//	printf("是否继续输入信息,请选择:0:否、1:是\n");
	//	scanf("%d", &flag);
	//}
	InsertNode(list, 1);
	InsertNode(list,2);
	InsertNode(list, 3);
	//打印链表
	print(list);
	printf("\n");
	//删除一个数据
	deleteNode(list, 3);
	print(list);
	return 0;

}

  • 9
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值