数据结构之链表的基本操作

1.什么是链表?

连表示结构体变量与结构变量连接在一起

链表结点中既要存储数据,也要存储下一个结点的地址

因此链表结点通常由若干个数据成员(数据域)和指针成员(指针域)组成

最简单的链表中只包含一个数据域和一个指针域

例1,创建一个包含3个结点的简单链表,每个节点包含一个整形数据成员和一个指针成员

编程思路

首先定义链表节点结构体

struct node//链表结点结构体类型

{int data;//数据域

struct node *next;//指针域

};

struct node a,b,c;//链表节点结构体变量

指针域的next类型是struct node*(指向struct node类型的指针类型),因为next要只想下一个结点(struct node 类型)

2. 有了链表结点 如何构成链表?

访问连表示总是从第一个开始顺序访问,因此需要定义一个专门的指针,用于指向链表的第一个结点,并称之为头指针

struct node *head;//定义指针变量

head=&a;//令头指针指向第一个结点

然后,依次在链表结点的数据域中存入数据,并通过指针域将链表结点连接起来

scanf("%d",&a.data);//把输入的数据存入到a结点中的数据域中

a.next=&b;//a的指针指向b结点的地址

scanf("%d",&b.data);

b.next=&c;

scanf("%d",&c.data);

c.next=Null;

链表的末结点没有后继结点,故其指针域赋值为空指针NULL,表示不指向任何结点

在上述程序段中,有意的对代码进行简化,再用定义变量(即静态内存分配)的方式创建链表结点。这种链表成为静态链表

由于静态链表相对于数组来说不具备多少优势,因而很少使用

在实际应用中,通常使用动态链表。即采用动态内存分配方式创建链表结点

3.怎么动态创建链表?

内存的动态分配:

是指在程序运行过程中随时地分配与回收内存

动态分配方式,是通过调用专门的函数来实现的

***c语言中提供了专门动态分配内存的函数——malloc 函数

原型:void *malloc(unsigned int n)

功能:申请分配长度为N字节的连续内存。

若成功,则返回分配内存的首地址;若失败,则返回空指针NULL。

在程序调用该函数时,失败几率非常低,故一般不需要判断是否分配成功

void*是一种通用指针类型,它与所有其他指针类型都是赋值兼容的

例2.利用动态内存分配方式分配一个整型数据的内存空间。

1,可以用malloc函数实现动态内存分配

2,一个int型数据在内存中是不是一定要占用4个字节呢? 不一定,在不用的c语言编译器中,同一种类型的数据其内存长度有可能不同

3,为了提高程序的通用性,可以利用sizeof运算符求出某种数据类型的内存长度。如sizeof(int)

#include
#include//调用malloc函数
int main(void)
{
int *p;
p=(int*)malloc(sizeof(int));//动态分配内存,,,在上面调用了malloc函数,malloc函数的返回值是一个void*,而我直接赋值给p为int型了,所以要加一个强制转换符(int*)
*p=100;//j=间接引用所分配的内存
printf("%d\n",*p);
free(p);
return 0;
}

动态内存申请+模块化设计

<1>创建链表(创建一个表头来表示一个链表)

链表其实就是将若干个结构体变量,通过指针连接起来构成的数据结构

链表中的结构体变量成为链表的结点

链表中的结点既要存储数据,也要存储下一个结点的地址。

创建头结点(链表表头)

结构体指针怎么变成结构体变量?

typedef语句

在c语言中,可以使用typedef语句为已存在的数据类型定义一个类型的别名

其一般形式为

typedef 类型说明符 类型别名

typedef unsigned int UINT;//定义类型别名

UINT a,b;

等效于 unsigned int a,b;

可以利用typedef语句为结构体类型等定义别名,从而简化代码,增强程序的可读性

struct node 
{int data;
struct node *next;
};
typedef struct node NODE;//定义类型别名
//从而NODE a,b,*p;
将等效于struct node a,b,*p;

内存的两种访问方式

1.随机访问方式

对数组来说,它的所有元素在内存中是连续存储的,因而很容易计算出每个元素的地址,从而可以直接访问数组中的任意一个元素

2.顺序访问方式

对于链表来说,不同的结点在内存中的存储位置是随机的,因而无法计算出每个结点的内存地址,从而只能从第一个结点开始依次访问

不带头结点的链表

若是将第一个结点的地址存储到一个专门的指针变量中,那么这种链表成为不带头结点的链表,用于存放第一个节点地址的指针变量成为头指针。

带头结点的链表

若是将第一个节点的地址存储到一个专门的结点的指针域中,那么这种链表成为带头结点的链表

:通过动态内存申请

<2>创建结点

<3>插入结点

<4>删除结点

<5>打印遍历链表()

你可能感兴趣的:(链表,数据结构,java)