数据结构—线性表

目录

介绍:

顺序表

创建顺序表

初始化顺序表

在顺序表中添加元素

遍历顺序表

插入一个元素

删除一个元素

查找数据

用堆内存分配内存

链表

单链表

创建链表

初始化链表

创建一个节点

遍历

在指定位置插入

删除一个节点

获取链表长度

删除链表中重复出现的数据

反转链表

快慢指针

删除链表中间节点

用快慢指针寻找倒数第K位置的数据

总代码

注:

循环链表

双向链表


介绍:

线性表是相同数据的集合,类似于数组,但比数组多了增删改查的功能,这些功能需要我们自己写,线性表分顺序表和链表

  • 顺序表:用一组连续的内存单元存储线性表的各种数据,逻辑上相邻的元素,实际上物理存储空间也是连续的,虽然叫顺序表,但在我们使用时还是用数组用来存储数据
  • **链表:**链表是用任意存储单元存储链表元素,链表数据的内存大概率不是连在一起的 ,链表中的每个节点不仅包含存储的信息,还包含上一节点和下一节点的地址,头节点不存数据

顺序表

创建顺序表

  • length:这是顺序表的元素个数,不是元素下标,这里的typedef struct定义的是一个没有名字的结构体,到下面的SeqList才是给这个结构体取别名

    //让程序更灵活
    typedef int ELemtype;

    //data数组的大小
    #define MAXSIZE 100

    typedef struct
    {
    ELemtype data[MAXSIZE];
    //表示顺序表中有几个元素
    int length;
    }SeqList;

初始化顺序表

复制代码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"


typedef int	ELemtype;
#define MAXSIZE	100

typedef struct
{
	ELemtype data[MAXSIZE];
	int	length;
}SeqList;


void SeqList_Init(SeqList* L)
{
	L->length = 0;
}

在顺序表中添加元素

复制代码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"


typedef int	ELemtype;
#define MAXSIZE	100
//创建顺序表
typedef struct
{
	ELemtype data[MAXSIZE];
	int	length;
}SeqList;

//初始化顺序表
void SeqList_Init(SeqList* L)
{
	L->length = 0;
}

//在顺序表中添加元素
int SeqList_Add(SeqList* L,ELemtype e)
{
	if (L->length >= MAXSIZE)
	{
		printf("顺序表已满");
		return 0;
	}
	else
	{
		L->data[L->length] = e;
		L->length++;
		return 0;
	}
}


void main(void)
{
	//创建顺序表1
	SeqList	list_1;

	//初始化顺序表
	SeqList_Init(&list_1);

	//在顺序表中添加元素
	SeqList_Add(&list_1, 2);

	printf("%d\n", list_1.data[list_1.length-1]);
}

遍历顺序表

复制代码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"


typedef int	ELemtype;
#define MAXSIZE	100
//创建顺序表
typedef struct
{
	ELemtype data[MAXSIZE];
	int	length;
}SeqList;

//初始化顺序表
void SeqList_Init(SeqList* L)
{
	L->length = 0;
}

//在顺序表中添加元素
int SeqList_Add(SeqList* L,ELemtype e)
{
	if (L->length >= MAXSIZE)
	{
		printf("顺序表已满");
		return 0;
	}
	else
	{
		L->data[L->length] = e;
		L->length++;
		return 0;
	}
}


//遍历顺序表
void SeqList_Elem(SeqList* L)
{
	if (L->length == 0)
	{
		printf("顺序表无元素\n");
	}
	else
	{
		for (int i = 0;i < L->length;i++)
		{
			printf("%d\n", L->data[i]);
		}
	}
}

void main(void)
{
	//创建顺序表1
	SeqList	list_1;

	//初始化顺序表
	SeqList_Init(&list_1);

	//在顺序表中添加元素
	SeqList_Add(&list_1, 1);
	SeqList_Add(&list_1, 2);
	SeqList_Add(&list_1, 3);

	//遍历顺序表
	SeqList_Elem(&list_1);
	


}

插入一个元素

插入一个元素逻辑,

**插入位置:**不能大于整个顺序表,不能在0位置插入,插入位置不能超过顺序表总元素的位置,如顺序表有3个元素,不能在插在第5个元素

逻辑:在插入元素后面的元素都要往后移一位,直到移到插入位置没有元素为止

  • **for (int i = L->length-1;i >=pos-1;i--),**这里length-1,是Length位置数据的下标,pos-1,也是代表pos位置的数据的下标

  • L->data[pos-1] = e;,表示将e赋值给pos位置

  • L->length++;,插入一个数据,顺序表数据增加一个

    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"

    typedef int ELemtype;
    #define MAXSIZE 100
    //创建顺序表
    typedef struct
    {
    ELemtype data[MAXSIZE];
    int length;
    }SeqList;

    //初始化顺序表
    void SeqList_Init(SeqList* L)
    {
    L->length = 0;
    }

    //在顺序表中添加元素
    int SeqList_Add(SeqList* L,ELemtype e)
    {
    if (L->length >= MAXSIZE)
    {
    printf("顺序表已满");
    return 0;
    }
    else
    {
    L->data[L->length] = e;
    L->length++;
    return 0;
    }
    }

    //遍历顺序表
    void SeqList_Elem(SeqList* L)
    {
    if (L->length == 0)
    {
    printf("顺序表无元素\n");
    }
    else
    {
    for (int i = 0;i < L->length;i++)
    {
    printf("%d\n", L->data[i]);
    }
    }
    }

    //插入一个元素
    int InSertElem(SeqList* L, int pos, ELemtype e)
    {
    if (L->length >= MAXSIZE)
    {
    printf("顺序表已满\n");
    return 0;
    }
    if (pos > MAXSIZE)
    {
    printf("顺序表没有怎么长\n");
    return 0;
    }
    if (pos > L->length||pos<1)
    {
    printf("插错位置了\n");
    return 0;
    }
    for (int i = L->length-1;i >=pos-1;i--)
    {
    L->data[ i+ 1] = L->data[i];
    }
    L->data[pos-1] = e;
    L->length++;
    return 1;
    }

    void main(void)
    {
    //创建顺序表1
    SeqList list_1;

    复制代码
    //初始化顺序表
    SeqList_Init(&list_1);
    
    //在顺序表中添加元素
    SeqList_Add(&list_1, 1);
    SeqList_Add(&list_1, 2);
    SeqList_Add(&list_1, 3);
    
      //在1位置插入5
    InSertElem(&list_1, 1, 5);
    
    //遍历顺序表
    SeqList_Elem(&list_1);

    }

删除一个元素

删除一个元素实际上是覆盖,假设想删除位置2的元素,你将位置3元素的值赋值给位置2,再将位置4的元素赋值给位置3,依次赋值,到最后一个元素赋值完,length--就行了

元素的增删改查实际就是元素覆盖,

复制代码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"


typedef int	ELemtype;
#define MAXSIZE	100
//创建顺序表
typedef struct
{
	ELemtype data[MAXSIZE];
	int	length;
}SeqList;

//初始化顺序表
void SeqList_Init(SeqList* L)
{
	L->length = 0;
}

//在顺序表中添加元素
int SeqList_Add(SeqList* L,ELemtype e)
{
	if (L->length >= MAXSIZE)
	{
		printf("顺序表已满");
		return 0;
	}
	else
	{
		L->data[L->length] = e;
		L->length++;
		return 0;
	}
}


//遍历顺序表
void SeqList_Elem(SeqList* L)
{
	if (L->length == 0)
	{
		printf("顺序表无元素\n");
	}
	else
	{
		for (int i = 0;i < L->length;i++)
		{
			printf("%d\n", L->data[i]);
		}
	}
}

//插入一个元素
int InSertElem(SeqList* L, int pos, ELemtype e)
{
	if (L->length >= MAXSIZE)
	{
		printf("顺序表已满\n");
		return 0;
	}
	if (pos > MAXSIZE)
	{
		printf("顺序表没有怎么长\n");
		return 0;
	}
	if (pos > L->length||pos<1)
	{
		printf("插错位置了\n");
		return 0;
	}
	for (int i = L->length-1;i >=pos-1;i--)
	{
		L->data[ i+ 1] = L->data[i];
	}
	L->data[pos-1] = e;
	L->length++;
	return 1;
}


//删除一个元素
int	DeleteElem(SeqList* L, int pos)
{
	if (pos < L->length || pos >= 1)
	{
		for (int i = pos - 1;i <= L->length - 1;i++)
		{
			L->data[i] = L->data[i + 1];
		}
		L->length--;
		return 1;
	}
}
void main(void)
{
	//创建顺序表1
	SeqList	list_1;

	//初始化顺序表
	SeqList_Init(&list_1);

	//在顺序表中添加元素
	SeqList_Add(&list_1, 1);
	SeqList_Add(&list_1, 2);
	SeqList_Add(&list_1, 3);
	InSertElem(&list_1, 1, 5);
	DeleteElem(&list_1, 2);
	//遍历顺序表
	SeqList_Elem(&list_1);

	
}

查找数据

复制代码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"


typedef int	ELemtype;
#define MAXSIZE	100
//创建顺序表
typedef struct
{
	ELemtype data[MAXSIZE];
	int	length;
}SeqList;

//初始化顺序表
void SeqList_Init(SeqList* L)
{
	L->length = 0;
}

//在顺序表中添加元素
int SeqList_Add(SeqList* L,ELemtype e)
{
	if (L->length >= MAXSIZE)
	{
		printf("顺序表已满");
		return 0;
	}
	else
	{
		L->data[L->length] = e;
		L->length++;
		return 0;
	}
}


//遍历顺序表
void SeqList_Elem(SeqList* L)
{
	if (L->length == 0)
	{
		printf("顺序表无元素\n");
	}
	else
	{
		for (int i = 0;i < L->length;i++)
		{
			printf("%d\n", L->data[i]);
		}
	}
}

//插入一个元素
int InSertElem(SeqList* L, int pos, ELemtype e)
{
	if (L->length >= MAXSIZE)
	{
		printf("顺序表已满\n");
		return 0;
	}
	if (pos > MAXSIZE)
	{
		printf("顺序表没有怎么长\n");
		return 0;
	}
	if (pos > L->length||pos<1)
	{
		printf("插错位置了\n");
		return 0;
	}
	for (int i = L->length-1;i >=pos-1;i--)
	{
		L->data[ i+ 1] = L->data[i];
	}
	L->data[pos-1] = e;
	L->length++;
	return 1;
}


//删除一个元素
int	DeleteElem(SeqList* L, int pos)
{
	if (pos < L->length || pos >= 1)
	{
		for (int i = pos - 1;i <= L->length - 1;i++)
		{
			L->data[i] = L->data[i + 1];
		}
		L->length--;
		return 1;
	}
}

//查找数据,看看顺序表中又名没有这个数据
int	FindElem(SeqList* L, ELemtype e)
{
	for (int i = 0;i <= L->length;i++)
	{
		if (L->data[i] == e)
		{

			printf("有这个数据,位置在%d\n",i+1);
			return 1;
		}
	}
	printf("没有\n");
	return 0;
}

void main(void)
{
	//创建顺序表1
	SeqList	list_1;

	//初始化顺序表
	SeqList_Init(&list_1);

	//在顺序表中添加元素
	SeqList_Add(&list_1, 1);
	SeqList_Add(&list_1, 2);
	SeqList_Add(&list_1, 3);
	InSertElem(&list_1, 1, 5);
	DeleteElem(&list_1, 2);
	//遍历顺序表 
	SeqList_Elem(&list_1);
	FindElem(&list_1, 5);
	


}

用堆内存分配内存

这里用malloc开辟结构体和数组,让结构体和数组在推内存中创建,节省栈内存空间,这时List_1,就是地址要注意 ,传参时就不用取地址符了

复制代码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"


typedef int	ELemtype;
#define MAXSIZE	100
//创建顺序表
typedef struct
{
	ELemtype *data;
	int	length;
}SeqList;

//用推内存初始化顺序表
SeqList* SeqList_Init()
{
	SeqList* L = (SeqList*)malloc(sizeof(SeqList));
	L->data = (ELemtype*)malloc(sizeof(ELemtype) * MAXSIZE);
	L->length = 0;
	return L;
}

//在顺序表中添加元素
int SeqList_Add(SeqList* L,ELemtype e)
{
	if (L->length >= MAXSIZE)
	{
		printf("顺序表已满");
		return 0;
	}
	else
	{
		L->data[L->length] = e;
		L->length++;
		return 0;
	}
}


//遍历顺序表
void SeqList_Elem(SeqList* L)
{
	if (L->length == 0)
	{
		printf("顺序表无元素\n");
	}
	else
	{
		for (int i = 0;i < L->length;i++)
		{
			printf("%d\n", L->data[i]);
		}
	}
}

//插入一个元素
int InSertElem(SeqList* L, int pos, ELemtype e)
{
	if (L->length >= MAXSIZE)
	{
		printf("顺序表已满\n");
		return 0;
	}
	if (pos > MAXSIZE)
	{
		printf("顺序表没有怎么长\n");
		return 0;
	}
	if (pos > L->length||pos<1)
	{
		printf("插错位置了\n");
		return 0;
	}
	for (int i = L->length-1;i >=pos-1;i--)
	{
		L->data[ i+ 1] = L->data[i];
	}
	L->data[pos-1] = e;
	L->length++;
	return 1;
}


//删除一个元素
int	DeleteElem(SeqList* L, int pos)
{
	if (pos < L->length || pos >= 1)
	{
		for (int i = pos - 1;i <= L->length - 1;i++)
		{
			L->data[i] = L->data[i + 1];
		}
		L->length--;
		return 1;
	}
}

//查找数据,看看顺序表中又名没有这个数据
int	FindElem(SeqList* L, ELemtype e)
{
	for (int i = 0;i <= L->length;i++)
	{
		if (L->data[i] == e)
		{

			printf("有这个数据,位置在%d\n",i+1);
			return 1;
		}
	}
	printf("没有\n");
	return 0;
}

void main(void)
{
	//创建顺序表1
	SeqList	*list_1;

	//初始化顺序表
	list_1=SeqList_Init();

	//在顺序表中添加元素
	SeqList_Add(list_1, 1);
	SeqList_Add(list_1, 2);
	SeqList_Add(list_1, 3);
	InSertElem(list_1, 1, 5);
	//DeleteElem(list_1, 2);
	//遍历顺序表 
	SeqList_Elem(list_1);
	FindElem(list_1, 2);
	


}

链表

单链表

创建链表

typedef struct node :表示定义一个名为node的结构体,在下面把这个结构体取别名为Node,

struct node* next :这里表示定义一个类型为node的指针

复制代码
#include "stdio.h"

typedef int ElemType;

typedef struct node
{
	struct node* next ;
	ElemType data;
}Node;

初始化链表

初始化链表就是创建头节点,将头节点在堆内存中创建

复制代码
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

typedef int ElemType;

typedef struct node
{
	struct node* next ;
	ElemType data;
}Node;

Node* Node_Init(void)
{
	Node* head = (Node*)malloc(sizeof(Node));
	head->next = NULL;
	head->data = 0;
	return head;
}

创建一个节点

创建一个节点分两种方式头插法,尾插法

  • 头插法:每次创建节点都在头节点的位置插入,头插法要先把头节点指向的下一个节点地址赋值给新创的节点next,再将头节点next指向新节点,如果先将头节点的next指向新节点,那后面节点的位置都找不着了

  • 尾插法:在链表尾部插入节点,要想在尾部插入数据,要先找到尾节点,注:Node* M = L; 这里不能是 Node* M = L->next;,如果链表没有数据那M==NULL,下面的while循环执行不了,这里直接把头节点赋值给M这里返回尾节点,是为了下次插入更方便,让下次插入直接找到尾节点不用进入while循环,让代码运行更快

    #include "stdio.h"
    #include "string.h"
    #include "stdlib.h"

    typedef int ElemType;

    typedef struct node
    {
    struct node* next ;
    ElemType data;
    }Node;

    //初始化链表
    Node* Node_Init(void)
    {
    Node* head = (Node*)malloc(sizeof(Node));
    head->next = NULL;
    head->data = 0;
    return head;
    }

    //创建一个节点(尾插法)
    Node* Node_Tail_create(NodeL,ElemType e)
    {
    Node
    N = (Node*)malloc(sizeof(Node));
    N->data = e;

    复制代码
    //这里不能是M=L->next
    Node* M = L;
    while (M->next!= NULL)
    {
    	M = M->next;
    }
    M->next = N;
    N->next = NULL;
    return N;

    }

    //创建一个节点(头插法)
    //每次插入数据都在头节点后面插入
    void Node_head_create(Node* L,ElemType e)
    {
    Node* N = (Node*)malloc(sizeof(Node));
    N->data = e;
    //把头节点指向的节点地址赋值给新创的节点
    N->next = L->next;
    L->next = N;
    }

遍历

复制代码
void listNode(Node* L)
{
	Node* M = L->next;
	while (M!= NULL)
	{
		printf("%d\n", M->data);
		M = M->next;
	}
}

在指定位置插入

复制代码
//在指定位置插入
void Inser_Node(Node* L, int pos,ElemType e)
{
	Node* N = (Node*)malloc(sizeof(Node));
	N->data = e;

	//Node* M = L;
	int i = 0;
	while (i< pos-1)
	{
		L = L->next;
		i++;
	}
	N->next = L->next;
	L->next = N;
}

删除一个节点

删除节点一定要把该节点的空间释放掉

复制代码
//删除节点(删除指定数字)
void Delete_Node_1(Node* L, ElemType e)
{
	while (L->next->data!= e&&L->data!=NULL)
	{
		L = L->next;
		if (L->next == NULL)
		{
			printf("该链表没有此数据");
		}
	}
	Node*M;
	M = L->next->next;
	free(L->next);
	L->next = M;
}

//删除指定位置节点
void Delete_Node_2(Node* L, int pos)
{
	for (int i=0;i < pos - 1;i++)
	{
		L = L->next;
		if (L == NULL)
		{
			printf("该链表没有这么长");
		}
	}
	Node* M = L->next->next;
	free(L->next);
	L->next = M;

}

获取链表长度

复制代码
//获取链表长度
int	ListLength(Node* L)
{
	int i = 0;
	for (i=0;L != NULL;i++)
	{
		L = L->next;
	}
	return i-1;
}

删除链表中重复出现的数据

链表的长度就是链表的最大值,如:链表长为6,链表最大数据为6

复制代码
//链表最大值也是链表长度,删除链表中重复出现的数据
void removeNode(Node* L)
{

	//计算出链表最大值
	int	M = 0;
	int MAX = 0;
	Node* L_1 = L->next;

	while (L_1 != NULL)
	{
		M = abs(L_1->data);
		if (M > MAX)
		{
			MAX = M;
		}
		L_1 = L_1->next;
	}
	printf("链表最大值为%d\n",MAX);
	//创建数值
	int* arr = (int*)malloc(sizeof(int) * (MAX+1));
	//给数值初始化
	for (int i = 0;i <=MAX;i++)
	{
		arr[i] = 0;
	}


	int indet = 0;
	Node* prev=L;
	Node* curr = L->next;
	while(curr!=NULL)
	{
		indet = abs(curr->data);

		if (arr[indet] == 0)
		{
			arr[indet] = 1;
			prev = curr;
			curr = curr->next;
		}

		else if (arr[indet] == 1)
		{
			prev->next = curr->next;
			free(curr);
			curr = prev->next;
		}
	}
	free(arr);
	
}

反转链表

复制代码
//反转链表
Node* reverseList(Node* L)
{
	Node* first = NULL;
	Node* second = L->next;
	Node* third = second->next;
	while (second != NULL)
	{
		third = second->next;
		second->next = first;
		first = second;
		second = third;
	}
	Node* head = (Node*)malloc(sizeof(Node));
	head->next = first;
	return head;
}

快慢指针

删除链表中间节点
复制代码
//删除链表中间节点
Node* DeleMinddleNode(Node* L)
{
	Node* S = L;
	Node* F = L->next;
	while (F != NULL)
	{
		F = F->next;
		if (F->next == NULL)
		{
			Node* M = S->next->next;
			free(S->next);
			S->next = M;
			return S;
		}
		S = S->next;
		F = F->next;
		if (F->next == NULL)
		{
			Node* M = S->next->next;
			free(S->next);
			S->next = M;
			return S;
		}

	}
用快慢指针寻找倒数第K位置的数据
复制代码
//寻找倒数第NUM个节点的数据
void findNode(Node* L,int NUM)
{
	Node* K=L;
	Node* M=L;
	int	a = 0;
	while (K ->next!= NULL)
	{
		K = K->next;
		a++;
		if (a >=NUM)
		{
			M = M->next;
		}
	}
	printf("%d\n", M->data);
}

总代码

复制代码
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

typedef int ElemType;

typedef struct node
{
	struct node* next ;
	ElemType data;
}Node;

//初始化链表
Node* Node_Init(void)
{
	Node* head = (Node*)malloc(sizeof(Node));
	head->next = NULL;
	head->data = 0;
	return head;
}

//创建一个节点(尾插法)
Node* Node_Tail_create(Node*L,ElemType e)
{
	Node* N = (Node*)malloc(sizeof(Node));
	N->data = e;

	//这里不能是M=L->next
	Node* M = L;
	while (M->next!= NULL)
	{
		M = M->next;
	}
	M->next = N;
	N->next = NULL;
	return N;
}

//创建一个节点(头插法)
//每次插入数据都在头节点后面插入
void Node_head_create(Node* L,ElemType e)
{
	Node* N = (Node*)malloc(sizeof(Node));
	N->data = e;
	//把头节点指向的节点地址赋值给新创的节点
	N->next = L->next;
	L->next = N;
}

//遍历
void listNode(Node* L)
{
	Node* M = L->next;
	while (M!= NULL)
	{
		printf("%d ", M->data);
		M = M->next;
	}
	printf("\n");
}

//在指定位置插入
void Inser_Node(Node* L, int pos,ElemType e)
{
	Node* N = (Node*)malloc(sizeof(Node));
	N->data = e;

	//Node* M = L;
	int i = 0;
	while (i< pos-1)
	{
		L = L->next;
		i++;
	}
	N->next = L->next;
	L->next = N;
}
//删除节点(删除指定数字)
void Delete_Node_1(Node* L, ElemType e)
{
	while (L->next->data!= e&&L->next!=NULL)
	{
		L = L->next;
		if (L->next == NULL)
		{
			printf("该链表没有此数据");
		}
	}
	Node*M;
	M = L->next->next;
	free(L->next);
	L->next = M;
}

//删除指定位置节点
void Delete_Node_2(Node* L, int pos)
{
	for (int i=0;i < pos - 1;i++)
	{
		L = L->next;
		if (L == NULL)
		{
			printf("该链表没有这么长");
		}
	}
	Node* M = L->next->next;
	free(L->next);
	L->next = M;

}

//获取链表长度
int	ListLength(Node* L)
{
	int i = 0;
	for (i=0;L != NULL;i++)
	{
		L = L->next;
	}
	return i-1;
}

void freeNode(Node* L)
{
	while (L->next != NULL)
	{
		Delete_Node_2(L,1);
	}
	L->next = NULL;
}

//寻找倒数第NUM个节点的数据
void findNode(Node* L,int NUM)
{
	Node* K=L;
	Node* M=L;
	int	a = 0;
	while (K ->next!= NULL)
	{
		K = K->next;
		a++;
		if (a >=NUM)
		{
			M = M->next;
		}
	}
	printf("%d\n", M->data);
}
//链表最大值也是链表长度,删除链表中重复出现的数据
void removeNode(Node* L)
{

	//计算出链表最大值
	int	M = 0;
	int MAX = 0;
	Node* L_1 = L->next;

	while (L_1 != NULL)
	{
		M = abs(L_1->data);
		if (M > MAX)
		{
			MAX = M;
		}
		L_1 = L_1->next;
	}
	printf("链表最大值为%d\n",MAX);
	//创建数值
	int* arr = (int*)malloc(sizeof(int) * (MAX+1));
	//给数值初始化
	for (int i = 0;i <=MAX;i++)
	{
		arr[i] = 0;
	}


	int indet = 0;
	Node* prev=L;
	Node* curr = L->next;
	while(curr!=NULL)
	{
		indet = abs(curr->data);

		if (arr[indet] == 0)
		{
			arr[indet] = 1;
			prev = curr;
			curr = curr->next;
		}

		else if (arr[indet] == 1)
		{
			prev->next = curr->next;
			free(curr);
			curr = prev->next;
		}
	}
	free(arr);
	
}

//反转链表
Node* reverseList(Node* L)
{
	Node* first = NULL;
	Node* second = L->next;
	Node* third;
	while (second != NULL)
	{
		third = second->next;
		second->next = first;
		first = second;
		second = third;
	}
	Node* head = (Node*)malloc(sizeof(Node));
	head->next = first;
	free(L);
	return head;
}


//删除链表中间节点
Node* DeleMinddleNode(Node* L)
{
	Node* S = L;
	Node* F = L->next;
	while (F != NULL)
	{
		F = F->next;
		if (F!=NULL&&F->next == NULL)
		{
			Node* M = S->next->next;
			free(S->next);
			S->next = M;
			return S;
		}
		S = S->next;
		F = F->next;
		if (F->next == NULL)
		{
			Node* M = S->next->next;
			free(S->next);
			S->next = M;
			return S;
		}

	}


}
void main(void)
{
	//遍历尾插法
	Node*list=Node_Init();
	Node* tail=Node_Tail_create(list,1); 
	tail = Node_Tail_create(tail, 2);
	tail = Node_Tail_create(tail, 1);
	tail = Node_Tail_create(tail, 4);
	tail = Node_Tail_create(tail, 2);
	tail = Node_Tail_create(tail, 4);
	tail = Node_Tail_create(tail, 7);
	tail = Node_Tail_create(tail, 8);
	listNode(list);
	removeNode(list);
	listNode(list);
	Node* list_1=reverseList(list);
	listNode(list_1);
	DeleMinddleNode(list_1);
	listNode(list_1);
		
}
注:

在指定位置插入和尾插法,遍历都·可以把M换成L,因为在C语言中函数参数是值传递,并不能改变外面的list,在函数中改变L的地址和L的next都不会影响外面的list

循环链表

循环链表和单链表一样,只不过,循环链表的尾节点,指向的头节点,使整个链表形成一个环

当遍历循环链表时,判断遍历的条件是 L->next !=L,

当用尾插法添加数据时,新节点的next不是NULL了,是头节点

双向链表

单链表存储结构中有,数据和指向下一节点的指针,只能由前一个节点找后一个节点,而双链表的存储结构有,数据和指向下一节点的指针加指向上一节点的指针,这样就能实现从后一节点找前一节点了,

相关推荐
Book思议-2 小时前
【数据结构实战】双向链表尾插法
c语言·数据结构·链表
做一个码农都是奢望2 小时前
计算机控制系统:最小拍控制系统设计入门
数据结构·算法
重生之后端学习2 小时前
31. 下一个排列
数据结构·算法·leetcode·职场和发展·排序算法·深度优先
没头脑的男大2 小时前
环形链表很曼妙的一个做题思路
数据结构·链表
shehuiyuelaiyuehao2 小时前
算法9,滑动窗口,长度最小的子数组
数据结构·算法·leetcode
计算机安禾2 小时前
【C语言程序设计】第33篇:二级指针与指针数组
c语言·开发语言·数据结构·c++·算法·visual studio code·visual studio
雨落在了我的手上2 小时前
C语言之数据结构初见篇(6):单链表的介绍(2)
数据结构
DANGAOGAO2 小时前
数据结构复习(持续更新)
数据结构
cui_ruicheng3 小时前
C++ 数据结构进阶:哈希表原理
数据结构·c++·算法·哈希算法