链表相关操作

很久没有更新,今天就以链表来进行新一轮的操作

简单介绍链表(C)

说直白一点:链表在C中就是自己用结构体实现一个数据类型,然后这些数据类型大量连接在一起构成一个存放数据的结构。与数组不一样的就是,在内存中数组是连续的,链表不是连续,是因为该结构体中有一成员是指针类型,有关于指针问题,以及指针大小,不知道的大家可以点击这里了解。
还需补充知识就是:结构体malloc动态开辟内存空间

最根本的单元:struct Node

typedef struct Node {
	int data;//成员中用来存放数据的
	struct Node* pNext;//成员中用来指向下一个单元的指针
}NODE,*PNODE;

在这里插入图片描述

一.链表的创建

首先要了解:头指针,头结点,首结点,尾结点等尤其前三者
在这里插入图片描述
头指针:就是一个单纯的指针类型数据,指向头结点
头结点:就是第一个结点,但是这个结点是一个傀儡结点,data部分不存放数据,仅仅在其指指针部分存放首结点的地址
首结点:就是第一个存放数据的有效结点
尾结点:最后一个存放有效数据的结点,其指针指向NULL
其实头指针的作用就相当于是一串葡萄的把,可以用这个把来将一串葡萄提起来

创建过程:

1.首先动态开辟一个结构体类型数据,作为头结点
2.为了保持头结点以后顺利返回,就创建一个尾结点一直移动,创建到哪里就到哪里
3.创建新节点并加入的过程如下:
在这里插入图片描述
4.最后返回头指针pHead就可以
代码如下:

PNODE create_List() {
	PNODE pHead = (PNODE)malloc(sizeof(NODE));
	PNODE pTail = pHead;
	pTail->pNext = NULL;
	int len = 0;
	int val = 0;
	printf("请输入长度:");
	scanf("%d", &len);
	for (int i = 0; i < len; i++)  {
		printf("请输入数值:");
		scanf("%d", &val);
		PNODE pNew = (PNODE)malloc(sizeof(NODE));
		pNew->data = val;
		pTail->pNext = pNew;
		pNew->pNext = NULL;
		pTail = pNew;
	}
	return pHead;
}

补充:其中的长度,数值等细节自己了解很容易读懂

二.链表的遍历输出

1.遍历前还是要明白,不管干什么都不要动头指针,只需要借助一个新指针代替就可以。
2.新节点 PNODE p = pHead->pNext ;一步一步后移就可以:p=p->pNext;

void traverse_List(PNODE pHead) {
	PNODE p = pHead->pNext;
	while (p != NULL) {
		printf("%d\t", p->data);
		p = p->pNext;//实现更新,指针后移
	}
	printf("\n");
}

三.链表的判空和求长度

1.判空就是:看指针指向的区域是否为NULL
2.长度也很好理解:就是在遍历的过程中加上一个数值积累并且返回,直接看代码就明白了

int is_empty(PNODE pHead) {
	PNODE p = pHead->pNext;
	if (p == NULL) {
		return 1;//返回1就是说明为空
	}
	else {
		return 0;//说明不是空
	}
}

int length_List(PNODE pHead) {
	PNODE p = pHead->pNext;
	int length = 0;
	if (is_empty(pHead))//是空,就返回1,就成立,长度就是0
		return length;
	else {
		while (p != NULL) {
			length++;//这里就是说前面提到的数值记录
			p = p->pNext;//和遍历一样尽进行指针后移
		}
	}
	return length;
}

四.给链表排序

这里选择冒泡排序,其实给链表排序不怎么常见,但是这里介绍是因为想要引入一种思想:同步更新,避开未知
1.冒泡排序就是两个变量之间的更新关系int i和int j之间以及与len长度之间的关系,我们类比数组,只不过是在数组几乎上用的是链表的内容进行比较
在这里插入图片描述
注意这两个变量的初始化与更新
在这里插入图片描述
代码如下:

void sort_List(PNODE pHead){
  int i,j,tmp;
  PNODE p = NULL;
  PNODE q = NULL;
  int len = length_List(pHead);
  for(i = 0,p = pHead->pNext; i < len - 1;++i,p = p->pNext){
    for(j = i + 1,q = p->pNext; j < len;++j,q = q->pNext ){
      if(p->data > q->data){
        tmp = p->data;
        p->data = q->data;
        q->data = tmp;
      }
    }
  }
  return;
}

五.链表的插入

1.关于链表的插入,我只是感慨于两行代码,而我仅仅是感觉到了皮毛,只知道这两行解决了所有插入条件的判断,不禁感慨这两行代码的精辟

while (p != NULL && i < pos - 1) {
		p = p->pNext;
		i++;
	}
	if (i > pos - 1 || p == NULL) {
		return 0;
	}

2.插入还需要了解的就是:整个插入过程
在这里插入图片描述
在这里插入图片描述
代码如下:

int inesert_List(PNODE pHead, int pos, int val) {
	int i = 0;
	PNODE p = pHead;
	while (p != NULL && i < pos - 1) {
		p = p->pNext;
		i++;
	}
	if (i > pos - 1 || p == NULL) {
		return 0;
	}
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	pNew->data = val;
	PNODE q = p->pNext;
	p->pNext = pNew;
	pNew->pNext = q;
	return 1;
}

六.链表的删除结点

1.更精辟的就是和插入一样,两行代码解决
在这里插入图片描述
2.不同的是:
在这里插入图片描述
链表删除直接就是将不要的结点去掉就可以
在这里插入图片描述
代码如下:

int delete_List(PNODE pHead, int pos) {
	int i = 0;
	PNODE p = pHead;
	while (i < pos - 1 && p->pNext != NULL) {
		p = p->pNext;
		i++;
	}
	if (i > pos - 1 || p->pNext == NULL) {
		return 0;
	}
	PNODE q = p->pNext;
	p->pNext = p->pNext->pNext;
	free(q);
	q = NULL;
	return 1;
}

总结:

以上就是一个链表的创建以及其他操作,其中关于内存释放以及内存开辟失败的处理细节没有写,希望大家真正在实现过程中不要忘了,欢迎批评指正,别忘了一键三连哦!!!谢谢观看!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值