线性单链表

数据结构—P3线性单链表

在这里插入图片描述

简介

在这里插入图片描述

线性表

概念

线性结构中的数据元素之间是一对一的关系,线性表List)表示零个或多个数据元素的有限序列

若将线性表记为(data(1)…data(n)),则表中的data(i-1)领先于data(i),称data(i-1)是data(i)的前驱元素,data(i)是data(i-1)的后继元素

线性表元素的个数n(n>0)定义为线性表的长度,当n=0时,称为空表

在这里插入图片描述


描述

线性表L可用二元组形式描述

L=(D,R)

D表示数据元素的集合

D={ai|i=0,1,2,…n}

R表示关系集合

R={<ai,ai+1>|0<=i<=n-2}

特征

1.对非空表,表头无前驱
2.对非空表,表尾无后继
3.其他的每个元素都有一个直接前驱和一个直接后继

链表

链表

以前在顺序结构中,每个数据元素只需要存数据元素信息就可以了;现在链式结构中,除了要存数据元素信息外,还要存储它的后继元素的存储地址

节点

为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息。我们把存储数据元素信息的域称为数据域,把存储直接后继位置称为指针域。指针域中存储的信息称做指针或链;这两部分信息组成数据元素ai的存储映像,称为结点(Node)

单链表

n个结点链结成一个链表,即为线性表的链式存储结构,因为此链表的每个结点中只包含指针域,所以叫做单链表

静态链表

首先我们让数组的元素都是由两个数据域组成,data和cur;用来存放数据元素,也就是通常我们要处理的数据;而游标cur相当于单链表中的next指针,存放该元素的后继在数组中的下标,我们把这种用数组描述的链表叫做静态链表

循环链表

将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表(circular linked list)

双向链表

双向链表(double linked list)是在单链表的每个结点中,再设置一个指向其前驱结点的指针域

实现

在这里插入图片描述

创建单链表结构体

创建文件编写程序

在这里插入图片描述

在这里插入图片描述
编写Makefile

在这里插入图片描述

test:test.o lklist.o
	gcc -o test test.o lklist.o
test.o:test.c lklist.h
	gcc -c test.c
lklist.o:lklist.c lklist.h
	gcc -c lklist.c
.PHONY:clean
clean:
	rm *.o

创建结构体

在这里插入图片描述

//宏定义int的别名为data_t
typedef int data_t;
//宏定义单链表节点和节点指正为listnode和*lklist
typedef struct node{
	data_t data;
	struct node *next;
}listnode, *lklist;

创建表函数

编写lklist.h

在这里插入图片描述
编写lklist.c

在这里插入图片描述

//创建表
lklist lklist_create(){
	//分配内存空间
	lklist H;
	H = (lklist)malloc(sizeof(listnode));
	if(H == NULL){
		printf("malloc is failed\n");
		return H;
	}

	//初始化
	H->data = 0;
	H->next = NULL;

	//返回表
	return H;
}

编写test.c

在这里插入图片描述
在这里插入图片描述

销毁表函数

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//释放表
lklist lklist_free(lklist H){
	//判断头节点是否为空
	lklist p;
	if(H == NULL){
		return NULL;
	}
	//依次释放节点空间
	p = H;
	while(H != NULL){
		p = H;
		free(p);
		H = H->next;
	}

	return NULL;
}

编写test.c

在这里插入图片描述

表尾插入函数

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//在表尾插入内容
int lklist_downinsert(lklist H,data_t value){
	lklist p,q;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	//创建插入的新节点
	if((p = (lklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc is failed\n");
		return -1;
	}
	//给新节点初始化内容
	p->data = value;
	p->next = NULL;
	//判断是否找到尾节点
	q = H;
	while(q->next != NULL){
		q = q->next;
	}
	//尾节点指向新创建的节点,新创建的节点成为尾节点
	q->next = p;

	return 0;
}

编写test.c

在这里插入图片描述

查询显示表函数

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//查询并显示所有内容
int lklist_show(lklist H){
	lklist p;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	//依次输出节点内容
	p = H;
	while(p->next != NULL){
		printf("%d  ",p->next->data);
		p = p->next;
	}
	printf("\n");

	return 0;
}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述

优化

在这里插入图片描述

插入操作

表头插入

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//在表头插入内容
int lklist_topinsert(lklist H,data_t value){
	lklist p,q;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	//创建插入的新节点
	if((p = (lklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc is failed\n");
		return -1;
	}
	//给新节点初始化内容
	p->data = value;
	p->next = NULL;

	q = H;
	p->next = q->next;
	q->next = p;

	return 0;

}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述


指定位置插入

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//指定位置插入内容
int lklist_insert(lklist H,data_t value,int pos){
	lklist p,q;
	int i = -1;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}

	if(pos < 0){
		printf("pos is invalid\n");
		return -1;
	}

	//创建插入的新节点
	if((p = (lklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc is failed\n");
		return -1;
	}
	//给新节点初始化内容
	p->data = value;
	p->next = NULL;

	q = H;
	while(i < pos-1){
		q = q->next;
		if(q == NULL){
			printf("pos is invalid\n");
			return -1;
		}
		i++;
	}
	
	p->next = q->next;
	q->next = p;

	return 0;
}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述


初始化创建

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//初始化创建
lklist lklist_initcreate(){
	//分配内存空间
	lklist H,p,q;
	int value;
	H = (lklist)malloc(sizeof(listnode));
	if(H == NULL){
		printf("malloc is failed\n");
		return H;
	}

	//初始化
	H->data = 0;
	H->next = NULL;
	
	printf("输入内容(-1结束输入):\n");
	while(1){
		printf("->:");
		scanf("%d",&value);
		if(value == -1){
			break;
		}else if((p = (lklist)malloc(sizeof(listnode))) == NULL){
			printf("malloc is failed\n");
			return H;
		}
		//给新节点初始化内容
		p->data = value;
		p->next = NULL;
		//判断是否找到尾节点
		q = H;
		while(q->next != NULL){
			q = q->next;
		}
		//尾节点指向新创建的节点,新创建的节点成为尾节点
		q->next = p;
	}

	return H;
}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述

查询操作

指定位置查询内容

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//查询指定位置内容
int lklist_poslocate(lklist H,int pos){
	lklist p;
	int i = -1;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}

	p = H;
	while(i < pos){
		p = p->next;
		if(p == NULL){
			printf("pos is invalid\n");
			return -1;
		}
		i++;
	}

	return p->data;

}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述


指定内容查询位置

编写lklist.h

在这里插入图片描述
编写lklist.c

在这里插入图片描述

//查询指定内容位置
int lklist_valuelocate(lklist H,data_t value){
	lklist p;
	int i = -1;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}

	p = H;
	while(1){
		p = p->next;
		if(p->data == value){
			break;
		}
		if(p == NULL){
			printf("pos is invalid\n");
			return -1;
		}
		i++;
	}

	return i+1;
}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述

删除操作

删除指定位置内容

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//删除指定位置内容
int lklist_posdelete(lklist H,int pos){
	lklist p,q;
	int i = -1;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}

	if(pos < 0){
		printf("pos is invalid\n");
		return -1;
	}


	q = H;
	while(i < pos-1){
		q = q->next;
		if(q == NULL){
			printf("pos is invalid\n");
			return -1;
		}
		i++;
	}
	
	p = q->next;
	q->next = p->next;

	free(p);
	q = NULL;
	
	return 0;

}

编写test.c

在这里插入图片描述
测试程序

在这里插入图片描述


删除指定内容

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//删除指定内容
int lklist_valuedelete(lklist H,data_t value){
	int pos;
	pos = lklist_valuelocate(H,value);
	lklist_posdelete(H,pos);

	return 0;
}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述

修改操作

修改指定位置内容

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//修改指定位置内容
int lklist_posmodify(lklist H,int pos,data_t value){
	
	lklist_posdelete(H,pos);
	lklist_insert(H,value,pos);
	return 0;

}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述


修改指定内容为指定内容

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//修改指定内容为指定内容
int lklist_valuemodify(lklist H,data_t rvalue,data_t value){
	int pos;
	pos = lklist_valuelocate(H,rvalue);
	lklist_posmodify(H,pos,value);
	return 0;
}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述

扩展

在这里插入图片描述

排序(从大到小)

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//对表进行排序,从大到小
int lklist_sortmax(lklist H){
	lklist p,q;
	int s;
	p = H;

	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	if(H->next == NULL){
		printf("H is only one \n");
		return -1;
	}

	p = p->next;

	while(p->next != NULL){
		q = p->next;
		while(q != NULL){
			if(q->data > p->data){
				s = p->data;
				p->data = q->data;
				q->data = s;

			}
			q = q->next;
		}
		p = p->next;
	}
	
	return 0;
}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述

表倒置

编写lklist.h

在这里插入图片描述

编写lklist.c

在这里插入图片描述

//对表进行倒置
int lklist_reverse(lklist H){
	lklist p,q;

	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	if(H->next == NULL || H->next->next == NULL){
		return 0;
	}

	p = H->next->next;
	H->next->next = NULL;

	while(p != NULL){
		q = p;
		p = p->next;

		q->next = H->next;
		H->next = q;
	}

	return 0;

}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述

排序(从小到大)

编写lklist.h

在这里插入图片描述
编写lklist.c

在这里插入图片描述

//对表进行排序,从小到大
int lklist_sortmin(lklist H){
	lklist_sortmax(H);
	lklist_reverse(H);
}

编写test.c

在这里插入图片描述

测试程序

在这里插入图片描述

整体代码

Makefile

test:test.o lklist.o
	gcc -o test test.o lklist.o
test.o:test.c lklist.h
	gcc -c test.c
lklist.o:lklist.c lklist.h
	gcc -c lklist.c
.PHONY:clean
clean:
	rm *.o

lklist.h

#ifndef __LKLIST_H__
#define __LKLIST_H__

//宏定义int的别名为data_t
typedef int data_t;
//宏定义单链表节点和节点指正为listnode和*lklist
typedef struct node{
	data_t data;
	struct node *next;
}listnode, *lklist;

//创建和删除操作
lklist lklist_create();//创建表
lklist lklist_free(lklist H);//释放表
lklist lklist_initcreate();//初始化创建
int lklist_posdelete(lklist H,int pos);//删除指定位置内容
int lklist_valuedelete(lklist H,data_t value);//删除指定内容

//插入操作
int lklist_downinsert(lklist H,data_t value);//在表尾插入内容
int lklist_topinsert(lklist H,data_t value);//在表头插入内容
int lklist_insert(lklist H,data_t value,int pos);//指定位置插入内容


//查询操作
int lklist_show(lklist H);//查询并显示所有内容
int lklist_poslocate(lklist H,int pos);//查询指定位置内容
int lklist_valuelocate(lklist H,data_t value);//查询指定内容位置

//修改操作
int lklist_posmodify(lklist H,int pos,data_t value);//修改指定位置内容
int lklist_valuemodify(lklist H,data_t rvalue,data_t value);//修改指定内容为指定内容

//排序操作
int lklist_sortmax(lklist H);//对表进行排序,从大到小
int lklist_sortmin(lklist H);//对表进行排序,从小到大
int lklist_reverse(lklist H);//对表进行倒置


#endif

lklist.c

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

/*-------------------------创建与删除--------------------------------*/

//创建表
lklist lklist_create(){
	//分配内存空间
	lklist H;
	H = (lklist)malloc(sizeof(listnode));
	if(H == NULL){
		printf("malloc is failed\n");
		return H;
	}

	//初始化
	H->data = 0;
	H->next = NULL;

	//返回表
	return H;
}

//初始化创建
lklist lklist_initcreate(){
	//分配内存空间
	lklist H,p,q;
	int value;
	H = (lklist)malloc(sizeof(listnode));
	if(H == NULL){
		printf("malloc is failed\n");
		return H;
	}

	//初始化
	H->data = 0;
	H->next = NULL;
	
	printf("输入内容(-1结束输入):\n");
	while(1){
		printf("->:");
		scanf("%d",&value);
		if(value == -1){
			break;
		}else if((p = (lklist)malloc(sizeof(listnode))) == NULL){
			printf("malloc is failed\n");
			return H;
		}
		//给新节点初始化内容
		p->data = value;
		p->next = NULL;
		//判断是否找到尾节点
		q = H;
		while(q->next != NULL){
			q = q->next;
		}
		//尾节点指向新创建的节点,新创建的节点成为尾节点
		q->next = p;
	}

	return H;
}

//释放表
lklist lklist_free(lklist H){
	//判断头节点是否为空
	lklist p;
	if(H == NULL){
		return NULL;
	}
	//依次释放节点空间
	p = H;
	while(H != NULL){
		p = H;
		free(p);
		H = H->next;
	}

	return NULL;
}

//删除指定位置内容
int lklist_posdelete(lklist H,int pos){
	lklist p,q;
	int i = -1;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}

	if(pos < 0){
		printf("pos is invalid\n");
		return -1;
	}


	q = H;
	while(i < pos-1){
		q = q->next;
		if(q == NULL){
			printf("pos is invalid\n");
			return -1;
		}
		i++;
	}
	
	p = q->next;
	q->next = p->next;

	free(p);
	q = NULL;
	
	return 0;

}

//删除指定内容
int lklist_valuedelete(lklist H,data_t value){
	int pos;
	pos = lklist_valuelocate(H,value);
	lklist_posdelete(H,pos);

	return 0;
}

/*-------------------------查询操作--------------------------------*/

//查询并显示所有内容
int lklist_show(lklist H){
	lklist p;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	//依次输出节点内容
	p = H;
	while(p->next != NULL){
		printf("%d  ",p->next->data);
		p = p->next;
	}
	printf("\n");

	return 0;
}
//查询指定位置内容
int lklist_poslocate(lklist H,int pos){
	lklist p;
	int i = -1;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}

	p = H;
	while(i < pos){
		p = p->next;
		if(p == NULL){
			printf("pos is invalid\n");
			return -1;
		}
		i++;
	}

	return p->data;

}

//查询指定内容位置
int lklist_valuelocate(lklist H,data_t value){
	lklist p;
	int i = -1;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}

	p = H;
	while(1){
		p = p->next;
		if(p->data == value){
			break;
		}
		if(p == NULL){
			printf("pos is invalid\n");
			return -1;
		}
		i++;
	}

	return i+1;
}
/*-------------------------插入操作--------------------------------*/

//在表尾插入内容
int lklist_downinsert(lklist H,data_t value){
	lklist p,q;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	//创建插入的新节点
	if((p = (lklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc is failed\n");
		return -1;
	}
	//给新节点初始化内容
	p->data = value;
	p->next = NULL;
	//判断是否找到尾节点
	q = H;
	while(q->next != NULL){
		q = q->next;
	}
	//尾节点指向新创建的节点,新创建的节点成为尾节点
	q->next = p;

	return 0;
}

//在表头插入内容
int lklist_topinsert(lklist H,data_t value){
	lklist p,q;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	//创建插入的新节点
	if((p = (lklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc is failed\n");
		return -1;
	}
	//给新节点初始化内容
	p->data = value;
	p->next = NULL;

	q = H;
	p->next = q->next;
	q->next = p;

	return 0;

}

//指定位置插入内容
int lklist_insert(lklist H,data_t value,int pos){
	lklist p,q;
	int i = -1;
	//判断头节点是否为空
	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}

	if(pos < 0){
		printf("pos is invalid\n");
		return -1;
	}

	//创建插入的新节点
	if((p = (lklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc is failed\n");
		return -1;
	}
	//给新节点初始化内容
	p->data = value;
	p->next = NULL;

	q = H;
	while(i < pos-1){
		q = q->next;
		if(q == NULL){
			printf("pos is invalid\n");
			return -1;
		}
		i++;
	}
	
	p->next = q->next;
	q->next = p;

	return 0;
}
/*-------------------------修改操作--------------------------------*/

//修改指定位置内容
int lklist_posmodify(lklist H,int pos,data_t value){
	
	lklist_posdelete(H,pos);
	lklist_insert(H,value,pos);
	return 0;

}

//修改指定内容为指定内容
int lklist_valuemodify(lklist H,data_t rvalue,data_t value){
	int pos;
	pos = lklist_valuelocate(H,rvalue);
	lklist_posmodify(H,pos,value);
	return 0;
}

/*-------------------------排序操作--------------------------------*/

//对表进行排序,从大到小
int lklist_sortmax(lklist H){
	lklist p,q;
	int s;
	p = H;

	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	if(H->next == NULL){
		printf("H is only one \n");
		return -1;
	}

	p = p->next;

	while(p->next != NULL){
		q = p->next;
		while(q != NULL){
			if(q->data > p->data){
				s = p->data;
				p->data = q->data;
				q->data = s;

			}
			q = q->next;
		}
		p = p->next;
	}
	
	return 0;
}

//对表进行排序,从小到大
int lklist_sortmin(lklist H){
	lklist_sortmax(H);
	lklist_reverse(H);
}

//对表进行倒置
int lklist_reverse(lklist H){
	lklist p,q;

	if(H == NULL){
		printf("H is NULL\n");
		return -1;
	}
	if(H->next == NULL || H->next->next == NULL){
		return 0;
	}

	p = H->next->next;
	H->next->next = NULL;
	while(p != NULL){
		q = p;
		p = p->next;

		q->next = H->next;
		H->next = q;
	}

	return 0;

}

test.c

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

//插入测试函数
int insert_test(){
	
	//创建表
	lklist H;
	H = lklist_create();
	//表尾插入内容
	lklist_downinsert(H,5);
	lklist_downinsert(H,6);
	//显示表所有内容
	lklist_show(H);

	//表头插入内容
	lklist_topinsert(H,4);
	lklist_topinsert(H,2);

	//显示所有内容
	lklist_show(H);

	//指定位置插入内容
	lklist_insert(H,1,0);
	lklist_insert(H,3,2);

	//显示表所有内容
	lklist_show(H);

	//释放表
	lklist_free(H);
}
//初始化创建测试函数
int initcreate_test(){
	//创建表
	lklist H;
	H = lklist_initcreate();
	//显示表所有内容
	lklist_show(H);
	//释放表
	lklist_free(H);
}

//删除测试函数
int delete_test(){
	//创建表
	lklist H;
	H = lklist_initcreate();
	
	//显示表所有内容
	lklist_show(H);

	lklist_posdelete(H,2);

	lklist_show(H);

	lklist_valuedelete(H,5);

	lklist_show(H);

	//释放表
	lklist_free(H);


}
//定位测试函数
int locate_test(){
	//创建表
	lklist H;
	H = lklist_initcreate();

	//显示表所有内容
	lklist_show(H);

	//显示指定位置内容
	printf("%d\n",lklist_poslocate(H,2));

	//显示指定内容位置
	printf("%d\n",lklist_valuelocate(H,3));

	//释放表
	lklist_free(H);
}
//修改测试函数
int modify_test(){
	lklist H;

	H = lklist_initcreate();

	lklist_show(H);

	lklist_posmodify(H,2,99);
	lklist_show(H);
	lklist_valuemodify(H,5,55);
	lklist_show(H);
	lklist_free(H);
}
//排序测试函数
int sort_test(){
	lklist H;

	H = lklist_initcreate();

	lklist_show(H);

	lklist_reverse(H);

	lklist_show(H);

	lklist_sortmax(H);

	lklist_show(H);

	lklist_sortmin(H);

	lklist_show(H);

	lklist_free(H);
}


//主函数
int main(int argc, const char *argv[])
{
	int chn,n = 1;
	while(n){ 
		printf("选择测试程序\n"); 
		printf("0.退出1.插入操作2.初始化创建3.删除操作4.查询操作5.修改操作6.排序操作:"); 
		scanf("%d",&chn); 
		switch(chn){ 
			case 0:n = 0;break; 
			case 1:insert_test();break; 
			case 2:initcreate_test();break; 
			case 3:delete_test();break;
			case 4:locate_test();break;
			case 5:modify_test();break;
			case 6:sort_test();break;
			default:printf("不在输入范围内请重新输入!\n"); 
		} 
	}
	return 0;
}

更多内容

数据结构 P1简介与分类

数据结构 P2线性顺序表

数据结构 P3线性单链表

数据结构 P4 栈

数据结构 P5 队列

数据结构 P6 树和二叉树

数据结构 P7 基础查找

数据结构 P8 哈希表

数据结构 P9 基础排序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CagePan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值