c/c++ 数据结构 单链表

单链表结构体类型定义:

#include<stdio.h>
#include<malloc.h>

typedef struct LNode {
	int data;
	struct LNode* next;//next自引用,指向同类型
}LinkNode;

单链表的创建方法一:头插法(倒过来)

void CreateLNodeH1(LinkNode*& L, int a[], int n)
{//头插法1,顺序相反
	L = (LinkNode*)malloc(sizeof(LinkNode));
	L->next = NULL;//注意如果不置空则是野指针
	int i = 0;
	LinkNode* s;
	for (i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));
		s->data = a[i];
		s->next = L->next;
		L->next = s;
	}
}

由于是h\rightarrow a_{n}\rightarrow a_{n-1}\rightarrow ....\rightarrow a_{2}\rightarrow a_{1},故得到的单链表元素索引与给定数组索引相反。

创建方法二:依然是头插法,但是在赋值时将数组最后一个元素赋值给第一个创建的节点(创建完后是最后一个),将数组倒数第二个元素赋值给第二个创建的节点(创建完后是倒数第二个节点),以此类推。

void CreateLNodeH2(LinkNode*& L, int a[], int n)
{//头插法2,反反的正,顺序相同
	L = (LinkNode*)malloc(sizeof(LinkNode));
	LinkNode* s; int i;
	L->next = NULL;
	for (i=0;i<n;i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));
		s->data = a[n-i-1];
		s->next = L->next;
		L->next = s;
	}
}

创建方法三:尾插法,通过双指针依次往后处理。

void CreateLNodeR(LinkNode*& L, int a[], int n)
{//尾插法,两个指针依次前进
	L = (LinkNode*)malloc(sizeof(LinkNode));
	LinkNode* p, * q=L;
	for (int i = 0; i < n; i++)
	{
		p = (LinkNode*)malloc(sizeof(LinkNode));
		p->data = a[i];
		q->next = p;
		q=p;
	}
	q->next = NULL;
}

最后顺序与数组相同。

单链表的初始化:用malloc函数开辟头节点的空间,且指向空。

void InitLNode(LinkNode*& L)
{
	L = (LinkNode*)malloc(sizeof(LinkNode));
	//给头节点开辟内存
	L->next = NULL;
}

单链表的销毁:从头节点开始依次往后释放各个节点的内存,剩最后一个节点时退出循环,再将其free();

void DestroyLNode(LinkNode*& L)
{
	LinkNode* pre,* p;
	pre = L; p = pre->next;
	while (p!= NULL)
	{
		free(pre);
		pre = p;
		p = pre->next;
	}
	//从头节点到尾节点依次释放空间,还剩最后一个节点时循环结束
	free(pre);//释放最后一个节点的内存
}

检查单链表是否为空:

bool LNodeEmpty(LinkNode* L)
{
	return L->next == NULL;
}
//头节点的next是否为空

求单链表的长度:每循环一次count+1,直到p为最后一个节点,返回count。

int LNodeLength(LinkNode* L)
{
	LinkNode* p = L;
	int count = 0;
	while (p ->next!= NULL)
	{
		p = p->next;
		count++;
	}
	return count;
}
//while循环,p依次往后

依次输出单链表元素:

void DispLNode(LinkNode* L)
{
	LinkNode* p = L->next;
	while (p != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}
//依次输出

根据单链表的索引取值:索引有效才为真,否则为假。

bool GetLNode(LinkNode* L, int i, int& e)
{
	LinkNode* p = L;
	int j = 0;
	while (j < i && p != NULL)
	{
		j++;
		p = p->next;
	}
	if (p == NULL)
		return false;
	else
	{
		e = p->data;
		return true;
	}
}

根据单链表的元素值求索引:当索引小于单链表长度且存在该元素才返回,否则返回-1。

int LocateLNode(LinkNode* L,int e)
{
	LinkNode* s = L->next;
	int count = 0;
	while (s->data!=e && s != NULL)
	{
		s = s->next;
		count++;

	}
	if (s == NULL)
		return -1;
	else
		return count;
}

在单链表中插入元素:当索引有效才插入。

void InsertLNode(LinkNode*& L, int i, int e)
{
	LinkNode* s = L,*r;
	int j = 0;
	while (j < i && s->next != NULL)
	{
		s = s->next;
		j++;
	}
	if (s == NULL)
	{
		printf("索引不合法。\n");
	}
	else
	{
		r = (LinkNode*)malloc(sizeof(LinkNode));
		r->data = e;
		r->next = s->next;
		s->next = r;
		DispLNode(L);
	}
}

插入元素时,先用malloc开辟一个节点空间,再进行赋值,然后通过

r->next = s->next;
s->next = r;

进行插入节点操作。

单链表的元素删除:同样,索引合法才能删除

void DeleteLNode(LinkNode*& L, int i, int& e)
{
	int j = 0;
	LinkNode* s=L,*r;
	while (j<i && s != NULL)
	{
		j++;
		s = s->next;
	}
	if (s == NULL)
		printf("索引不合法。\n");
	else
	{
		if(s->next==NULL)
			printf("索引不合法。\n");
		else
		{
			e = s->next->data;
			r = s->next;
			s->next = s->next->next;
			free(r);
			DispLNode(L);
		}
	}

}

在进行元素删除操作时,先将值赋出去,再

 r = s->next;
s->next = s->next->next;
free(r);

如图:

最后,通过main()函数实现。 

int main()
{
	LinkNode* L;
	int a[] = { 1,2,3,4,5,6,7 };
	InitLNode(L);
	CreateLNodeH2(L, a, 7);
	DispLNode(L);
	int e1 = 0;
	if (GetLNode(L, 2, e1))
	{
		printf("%d\n", e1);
	}
	DispLNode(L);
	bool bo = LNodeEmpty(L);
	if (bo)
	{
		const char* a = "True";
		printf("\"The list is empty\" is %s.\n", a);
	}
	else
	{
		const char* a = "False";
		printf("\"The list is empty\" is %s.\n", a);
	}
	printf("The locate of 3 is %d.\n",LocateLNode(L,3));
	InsertLNode(L,4,100);
	int e = 0;
	DeleteLNode(L, 8, e);
	printf("%d\n", e);
	DestroyLNode(L);
	return 0;
}

其中部分对元素的查找,插入和删除中有些是逻辑位置,有些是物理位置。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单链表是一种常见的数据结构,用于存储一系列的节点连接起来的数据。 在C语言中,我们可以使用结构体来定义一个节点,包含一个数据域和一个指向下一个节点的指针域。代码如下: ```c struct Node { int data; struct Node* next; }; ``` 然后,我们可以定义一个指向链表头部的指针,表示整个链表的起始位置。初始化链表时,这个指针可以指向NULL。 ```c struct Node* head = NULL; ``` 接下来,我们可以实现一些基本的操作,例如插入节点、删除节点、遍历链表等。 插入节点的过程包括创建一个新节点,并将其插入到链表中适当的位置。 ```c void insertNode(int value) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = value; newNode->next = NULL; if (head == NULL) { head = newNode; } else { struct Node* curr = head; while (curr->next != NULL) { curr = curr->next; } curr->next = newNode; } } ``` 删除节点的过程需要找到目标节点,并调整前后节点的指针。 ```c void deleteNode(int value) { if (head == NULL) { return; } if (head->data == value) { struct Node* temp = head; head = head->next; free(temp); return; } struct Node* prev = head; struct Node* curr = head->next; while (curr != NULL && curr->data != value) { prev = curr; curr = curr->next; } if (curr != NULL) { prev->next = curr->next; free(curr); } } ``` 遍历链表的过程是从头节点开始,依次打印每个节点的数据。 ```c void printList() { struct Node* curr = head; while (curr != NULL) { printf("%d ", curr->data); curr = curr->next; } printf("\n"); } ``` 这是一个简单的单链表的实现示例,你可以根据需要进一步扩展和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值