其他分享
首页 > 其他分享> > 链表学习总结

链表学习总结

作者:互联网

为什么学习链表。

链表和数组的区别


链表:包括数据域和指针域;

例如:

//例如:
struct student
{
    int id;
    //定义一个指针是他本身类型
    struct student *next;
    //内部有一个指针可以指向下一个数据的数据域;
}


动态链表(malloc动态分配内存)和静态链表(基本上不用);

带头链表和不带头链表,但一般都用带头链表。

不带头的:如果在前面插入一个数据,则头节点仍然是指向第二个,头节点不固定。

带头链表:第二个才是有效节点,第一个是头节点。

 

 双向链表:

1、结构体可以嵌套另外一个结构体的任何类型变量:

typedef struct A
{
    int id;
    char *p;
}A;

typedef struct B
{
    int a;
    A tmp1;
    A *p1;
}B;

2、结构体不能嵌套本结构体的普通变量,(因为结构体本生没有分配内存空间)

        本结构体的类型大小无法确定,类型本质; 是固定大小的内存块别名。

3、结构体嵌套本结构体的指针变量是可以的。

typedef struct A
{
    int id;
    char *p;
}A;

typedef struct B
{
    int a;
    A tmp1;
    A *p1;

    struct B tmp2; //error
    struct B *next //指针变量类型大小固定
}B;

静态链表:

typedef struct A
{
    int data;
    char name[100];
    A *next; //指针域
}A;

int main()
{
    //初始化结构体变量;
    stu s1 = {1,"mike",NULL};
    stu s1 = {2,"lily",NULL};
    stu s1 = {3,"lilei",NULL};

    s1.next = &s2; //s1的next指针指向s2
    s2.next = &s3;
    s3.next = NULL;
}

链表的每一个节点就是一个结构体

 指针指向谁就把谁的地址赋值给它;

 

循环遍历打印链表数据

 

 

动态链表:-------单向链表的实现

动态分配空间:malloc

 

typedef struct Node
{
	int id;
	struct Node* next;//指针域
}Node;

//创建头节点;
//链表的头结点地址由函数值返回
Node* SListCreat()
{
	Node* head = NULL;

	//头节点作为标志,不存储有效数据
	head = (Node*)malloc(sizeof(Node));
	//给head 的成员变量赋值

	head->id = -1;//无效数据
	head->next = NULL;

	//定义一些辅助变量;
	Node *pCur = head;
	Node* pNew = NULL;

	int data;

	while (1)
	{
		printf("请输入数据:");
		scanf("%d",&data);

		if (data == -1)
		{
			break;
		}

		//新节点
		pNew = (Node*)malloc(sizeof(Node));
		if (pNew == NULL)
		{
			continue;
		}

		//如果成功了,给pNew成员赋值
		pNew->id = data;
		pNew->next = NULL;

		//开始链表建立关系
		//当前结点的next指向pNew
		pCur->next = pNew;
		pNew->next = NULL;

		//把pCur 移动到pNew,相当于pCure 指向pNew
		pCur = pNew;



	}

}

链表的插入

 

 

 

 插入结点的代码

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


typedef struct Node
{
	int id;
	struct Node* next;//指针域
}Node;

//创建头节点;
//链表的头结点地址由函数值返回
Node* SListCreat()
{
	Node* head = NULL;

	//头节点作为标志,不存储有效数据
	head = (Node*)malloc(sizeof(Node));
	//给head 的成员变量赋值

	head->id = -1;//无效数据
	head->next = NULL;

	//定义一些辅助变量;
	Node *pCur = head;
	Node* pNew = NULL;

	int data;

	while (1)
	{
		printf("请输入数据:");
		scanf_s("%d",&data);

		if (data == -1)
		{
			break;
		}

		//新节点
		pNew = (Node*)malloc(sizeof(Node));
		if (pNew == NULL)
		{
			continue;
		}

		//如果成功了,给pNew成员赋值
		pNew->id = data;
		pNew->next = NULL;

		//开始链表建立关系
		//当前结点的next指向pNew
		pCur->next = pNew;
		pNew->next = NULL;

		//把pCur 移动到pNew,相当于pCure 指向pNew
		pCur = pNew;



	}
	return head;
}



//链表的遍历
int SListPrint(Node* head)
{
	if (head == NULL)
	{
		return -1;
	}

	//取出第一个有效结点(头节点的next)
	Node* pCur = head->next;
	while(pCur != NULL)
	{
		printf("%d->", pCur->id);

		pCur = pCur->next;
	}
	printf("NULL\n");
}

int SListNodeInsert(Node* head, int x, int y)
{
	if (head == NULL)
	{
		return -1;
	}

	Node *pPre = head;
	Node* pCur = head->next;

	while (pCur !=NULL)
	{
		//当pCur 不等于空的时候就往下走
		if (pCur->id == x)
		{
			break;
		}
		//如果没有找到,就往右移动一位
		pPre = pCur;
		pCur = pPre->next;
	}

	//给新结点动态分配空间;
	Node* pNew = (Node*)malloc(sizeof(Node));\
		if (pNew == NULL)
		{
			return -2;
		}
	//给新的成员变量赋值
	pNew->id = y;
	pNew->next = NULL;

	//插入指定位置
	pPre->next = pNew;
	pNew->next = pCur;




	return 0;
}

 
int main()
{
	//定义一个头节点
	Node* head = NULL;

	head = SListCreat();//创建头节点
	SListPrint(head);

	SListNodeInsert(head,5,4);//在5的后面插入4
	SListPrint(head);//打印

	printf("\n");
	system("pause");
}

删除指定的结点:

 

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


typedef struct Node
{
	int id;
	struct Node* next;//指针域
}Node;

//创建头节点;
//链表的头结点地址由函数值返回
Node* SListCreat()
{
	Node* head = NULL;

	//头节点作为标志,不存储有效数据
	head = (Node*)malloc(sizeof(Node));
	//给head 的成员变量赋值

	head->id = -1;//无效数据
	head->next = NULL;

	//定义一些辅助变量;
	Node *pCur = head;
	Node* pNew = NULL;

	int data;

	while (1)
	{
		printf("请输入数据:");
		scanf_s("%d",&data);

		if (data == -1)
		{
			break;
		}

		//新节点
		pNew = (Node*)malloc(sizeof(Node));
		if (pNew == NULL)
		{
			continue;
		}

		//如果成功了,给pNew成员赋值
		pNew->id = data;
		pNew->next = NULL;

		//开始链表建立关系
		//当前结点的next指向pNew
		pCur->next = pNew;
		pNew->next = NULL;

		//把pCur 移动到pNew,相当于pCure 指向pNew
		pCur = pNew;



	}
	return head;
}



//链表的遍历
int SListPrint(Node* head)
{
	if (head == NULL)
	{
		return -1;
	}

	//取出第一个有效结点(头节点的next)
	Node* pCur = head->next;
	while(pCur != NULL)
	{
		printf("%d->", pCur->id);

		pCur = pCur->next;
	}
	printf("NULL\n");
}

int SListNodeInsert(Node* head, int x, int y)
{
	if (head == NULL)
	{
		return -1;
	}

	Node *pPre = head;
	Node* pCur = head->next;

	while (pCur !=NULL)
	{
		//当pCur 不等于空的时候就往下走
		if (pCur->id == x)
		{
			break;
		}
		//如果没有找到,就往右移动一位
		pPre = pCur;
		pCur = pPre->next;
	}

	//给新结点动态分配空间;
	Node* pNew = (Node*)malloc(sizeof(Node));\
		if (pNew == NULL)
		{
			return -2;
		}
	//给新的成员变量赋值
	pNew->id = y;
	pNew->next = NULL;

	//插入指定位置
	pPre->next = pNew;
	pNew->next = pCur;
	return 0;
}

//删除结点
int SListNodeDL(Node *head,int x)
{
	if (head == NULL)
	{
		return -1;
	}
	int flag = 0;//建立一个标志位,0 代表没有找到,1代表找到

	Node* pPre = head;
	Node* pCur = head->next;

	while (pCur != NULL)
	{
		//当pCur 不等于空的时候就往下走
		if (pCur->id == x)
		{
			pPre->next = pCur->next;
			free(pCur);
			pCur = NULL;
			flag = 1;
			break;
		}
		//如果没有找到,就往右移动一位
		pPre = pCur;
		pCur = pPre->next;
	}

	if (flag == 0)
	{
		printf("没有值的为%d",x);
		return -2;
	}

	return 0;
}



int main()
{
	//定义一个头节点
	Node* head = NULL;

	head = SListCreat();//创建头节点
	SListPrint(head);

	SListNodeInsert(head,5,4);//在5的后面插入4
	SListPrint(head);//打印

	//删除5 结点
	SListNodeDL(head, 5, 4);//在5的后面插入4
	SListPrint(head);//打印

	printf("\n");
	system("pause");
}

清空链表

//清空链表,释放所有结点
int SListNodeDestroy(Node* head)
{
	if (head == NULL)
	{
		return -1;
	}
	Node* tmp = NULL;
	while (head != NULL)
	{
		//保存head 的下一个结点
		tmp = head->next;
		free(head);
		head = NULL;
		//head 指向tmp;
		head = tmp;
	}
}

 

标签:总结,学习,head,NULL,pNew,Node,链表,pCur,next
来源: https://blog.csdn.net/weixin_53700782/article/details/122288365