编写链表的产生的问题

问题描述:
结构体定义结构体指针变量"L"即一个结点,“L”指向第一个结点首地址。定义一个创建函数来创 建链表。而使用“L”时,需要将“L”初始化,即将“L”传入创建函数之前需要初始化“L”,或者直接调用 “L”的地址即“&L”。
下方采用的就是第二种方式,功能函数采用“双重指针”(ListL或struct LinkList**L)定义形参来接收传入函数的“L”的地址,然后再进行其他操作。这种方式避免了“L”的初始化。(typedef struct LinkList List)
第二种方式函数收到的时“L”的地址,以*M的形式就可以定位到“L”,然后进行开辟空间来开辟新结点。而第一种方式,初始化“L”后,可直接传“L”,L为头结点首地址,也为地址,而且是main函数种所声明的,所以函数结束也不会释放空间(并不在函数中开辟的空间)。

#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
struct LinkList {
	ElemType data;
	struct LinkList* next;
};
typedef struct LinkList* List;
#define LZN sizeof(struct LinkList) 
#define ERROR 0

//创建链表
void create_List(List* M, int n) {//注意这里的struct LinkList**M(List*M)千万别写成struct LinkList*M
    struct LinkList* p;           //因为需要对L开辟空间,L里存储的是结构体变量首地址,而传过来的是L的地址
	*M = (List)malloc(LZN);       //需要再来一重指针接收L地址,以*M引用L内的内容,List*M形式比较容易区分
	(*M)->data = n;
	(*M)->next = NULL;
	for (int i = 1;i <= n;i++) {
		p = (List)malloc(LZN);
		p->data = i;
		p->next = (*M)->next;
		(*M)->next = p;
	}
}

//插入元素
void ListInsert(List* L, int i, ElemType e) {
	struct LinkList* p,* q;
	int j = 1;
	p = (*L);
	while (p&&j<i) {
		p = p->next;
		++j;
	}
	if (!p||j>i) {
		return ERROR;
	}
	q = (List)malloc(LZN);
	q->data = e;
	q->next = p->next;
	p->next = q;
}

//删除元素
void ListDelete(List* M, int i,ElemType*e) {
	struct LinkList* p;
	struct LinkList* q;
	int j = 1;
	p = *M;
	while (p&&j<i) {
		p = p->next;
		j++;
	}
	if (!p||j>i) {
		return ERROR;
	}
	q = p->next;
	*e = q->data;
	p->next = q->next;
	free(q);
}

//整表删除
void ClearList(List*M) {
	struct LinkList* p;
	struct LinkList* q;
	p = (*M)->next;
	while (p) {
		q = p->next;
		free(p);
		p = q;
	}
	(*M)->next = NULL;
}
void main() {
	struct LinkList* L;
	struct LinkList* p;
	int e;
	//int m;
	//e = &m;
	ElemType n;
	n = 5;
	
	//创建部分测试
	void create_List(List* L, int n);
	create_List(&L,n);
	p = L;                                        //将L首地址赋给p,对p初始化
	printf("创建链表\n");
	for (int i = 0;i <= n;i++) {
		printf("%d ",p->data);
		p = p->next;                             
	}                                             //循环结束,p指向最末尾
	printf("\n");
	
	//插入部分测试
	p = L;                                        //重新将L首地址赋给p,为后面循环准备
	void ListInsert(List* L, int i, ElemType e);
	ListInsert(&L, 3, 12);
	printf("链表插入\n");
	for (int i = 0;i <= n+1;i++) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");

	//删除部分测试
	p = L;
	void ListDelete(List * M, int i, ElemType * e);
	ListDelete(&L, 3, &e);                      //取e的地址,用于ListDelete函数接收,再向这个地址赋值,即为e的值
	printf("删除元素\n");
	for (int i = 0;i <= n ;i++) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
	printf("删除的元素:%d\n",e);

	//整表删除测试
	
	void ClearList(List * M);
	ClearList(&L);
	p = L;
	printf("整表删除\n");
	while(p) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

下方为第一种方式,(只编写了“创建”、“插入”功能函数)定义“L”之后,对“L”进行初始化,分配了一个结点空间,创建了头结点,然后将初始化之后的“L”传入功能函数,再完成后续操作。功能函数定义了结构体指针变量(单指针struct LinkList*L)来接收传入的“L”,对于带有头结点的链表比较友好。

#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
struct LinkList {
	ElemType data;
	struct LinkList* next;
};
#define LZN sizeof(struct LinkList) 
#define ERROR 0

//创建链表
void create_List(struct LinkList* M, int n) {
	struct LinkList* p;           
	for (int i = 1;i <= n;i++) {
		p = (struct LinkList*)malloc(LZN);
		p->data = i;
		p->next = M->next;
		M->next = p;
	}
}

//插入元素
void ListInsert(struct LinkList* L, int i, ElemType e) {
	struct LinkList* p, * q;
	int j = 1;
	p = L;
	while (p && j < i) {
		p = p->next;
		++j;
	}
	if (!p || j > i) {
		return ERROR;
	}
	q = (struct LinkList*)malloc(LZN);
	q->data = e;
	q->next = p->next;
	p->next = q;
}

void main() {
	struct LinkList* L;
	struct LinkList* p;
	int e;
	ElemType n;
	n = 5;
	L = (struct LinkList*)malloc(LZN);       //初始化"L",后续需要将L直接传入,而不是传L地址,故要先初始化。
	L->data = n;
	L->next = NULL;
	//创建部分测试
	void create_List(struct LinkList* L, int n);
	create_List(L, n);
	p = L;                                        //将L首地址赋给p,对p初始化
	printf("创建链表\n");
	for (int i = 0;i <= n;i++) {
		printf("%d ", p->data);
		p = p->next;
	}                                             //循环结束,p指向最末尾
	printf("\n");

	//插入部分测试
	void ListInsert(struct LinkList* L, int i, ElemType e);
	ListInsert(L, 3, 12);
	p = L;                                        //将L首地址赋给p,对p初始化
	printf("创建链表\n");
	for (int i = 0;i <= n+1;i++) {
		printf("%d ", p->data);
		p = p->next;
	}                                             //循环结束,p指向最末尾
	printf("\n");
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值