C语言复习:(八)链表

问题:

1.链表有什么作用?

2.如何使用链表制作一个无限输入的空间,怎样实现需要内存就自动添加?

3.静态链表是什么?动态链表如何制作?

4.链表怎么输入,读取,释放内存?如何将表针移动到指定位置?

问题解决:

1.链表需要一个指向自己的指针:

首先制作一个链表类,结构体中需要放置一个指向自己的对象,对象需要指针类型,不然无法为其分配内存。其他成员根据需要添加。

//---------------------------文明时代游戏无限回合链表-------------------------
typedef struct country
{
    long long people;
    long long money;
    long long ecolomic;
    float Technology;
    int LandNum;
    char ID;
    int Exist;
    char Name[100]; 
};

//--------国家类---------

typedef struct LinkList
{
	int Num;            //链表中第几个
	struct
    {
        int Round;
        country* country_object[3450]    //文明时代一共3400个地,国家小于3400个。
        
    }Round;
	LinkList* next;     //链表节点

}LinkList;

图1

上述为文明时代游戏无限回合的链表。

其中next成员能不断指向自己的next形成链表。

2.链表为自己申请内存:

通过实现一个表针实现。首先定义一个表头,把表头的首地址给表针,表针就形成了和表头指向同一地址的指针。

typedef struct LinkList
{
    int Num;
    int Data;
    LinkList* next;
}LinkList;

//定义链表类

LinkList* Head = (LinkList*)malloc(sizeof(LinkList));

//定义表头

LinkList* Needle = (LinkList*)malloc(sizeof(LinkList));

//定义表针

Needle = Head;

//让结构体指针指向同一个地址

 图2

然后用如下语句实现不断指向下一个对象。

Needle = Needle->next;

图3

图3实现了表针的移动。最后表针移动到最后需要把指针对象设为NULL方便判定结束。

如下图为新成员申请内存:

void New_Load_Fun(int Num,int Data)
{
	Needle->next = (LinkList*)(malloc(sizeof(LinkList)));

//内存申请

	if (Needle->next == NULL)
	{
		exit(1);
	}

//内存申请出问题直接返回,因为如下操作在内存申请失败都是非法的,VS会严重警告。

	Needle->next->Data = Data;
	Needle->next->Num = Num;

//数据给予模块

	Needle = Needle->next;

//表针移动模块
}

图3 

特别注意:

1.函数的形参本质是获取变量的值付给形参参与函数运算,所以不会改变变量本身的数值。

如果函数的形参是变量的地址,就能将变量的地址赋给形参,形参的操作不会改变地址本身,但是能够改变地址中的值。

2.对于全局变量也是:函数如果直接调用全局变量,那么可以直接改变全局变量的值。

如果函数把全局变量作为形参,那么只是把全局变量的算数值赋值给形参,全局变量值不会被改变。

函数中如果调用了1级指针,那么形参就应该给2级及其以上指针才能改变变量值。

函数操作中调用了n级指针,那么形参就必须给予n+1及其以上级指针才能改变变量值;

3.对于常量,能定义N层指针变量,不断指向一个变量。

对于结构体变量:只有.和->两种调用成员方式,如果定义为:

MyStruct** Object  = (MyStruct**)malloc(sizeof(MyStruct));
//定义合法
Object->->next;
//明显调用不合理

图4

上述调用是非法的。

结构体变量无法定义为2级及其以上级别的指针对象。

所以:

void LoadFun(Link* Self)
{
    Self->next = (Link*)malloc(sizeof(Link));
    /*上述赋值不合法:形参Self是Link*类型,是一级指针
    (Link*)malloc(sizeof(Link))申请内存操作是赋值给一级指针的,
    此时形参需要是二级指针其值才能被改变。
    
    即Link** Self
    */
}


void LoadFun(Link** Self)
{
    *Self->next = (Link*)malloc(sizeof(Link));
    /*上述赋值不合法:
    Self是二级结构体指针,无法调用成员;即使加了地址访问符:*变成*Self,也无法访问成员。
    */
}

图5 

综上:每个注册函数只能专门给某个结构体使用,不能对任意结构体类型使用。

3.将表针移动到指定地方:结构体中定义一个变量int Num;记录这是第几曾指针;

void MoveNeedle_Fun(int DstNum)
{
    Needle = Head;

//初始化为0

    for(;;)
    {
        if(Needle->Num == DstNum)
        {
            break;
        }

        Needle = Needle->Next;
//表针后移一位
    }
}

图6

上述为将表针移动到指定位置。

有了移动表针到任意地方的函数,就能够实现任意位置读入与输出。

4.释放链表内存:

需要再定义一个存储中间量来存储表针的下一个成员next,以防释放了表针位置之后,后面的地址就再也找不到了。

void LinkListFree_Fun()
{
	while (1)
	{
		if (Free_A == NULL)
		{
			break;
		}

		Free_B = Free_A->next;
		//存储下一个对象的地址

		free(Free_A);
		//从前往后释放

		Free_A = Free_B;
		//A的下一个地址再次给A
	}
	object = NULL;
}

图7

图7代码实现了成员内存逐个释放。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值