链表的实现

目录

注意:我下面的链表都是有头节点的,data保存了整个链表的节点个数

单链表

头插法

尾插法

删除节点

demo

双链表

头插法

尾插法

删除节点-

demo

单向循环链表

头插法

尾插法

删除节点

demo

双向循环链表

头插法

尾插法

删除节点

demo


注意:我下面的链表都是有头节点的,data保存了整个链表的节点个数

单链表

 上面每一个模块都是一个节点,也就是一个结构体,里面存放了一个指针变量和一个data变量,最后一个节点值指向空

头插法

 将新的节点插在链表除去头节点的第一个位置,最后一个


//头插法
// 把地址给那个变量,就是让那个指针变量指向自己
// 注意左边是指针,右边是地址
//传入头节点、数据域
void headInsert(Node* list, int data) {
    
	Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个空间返回一个地址,新的节点指针node指向这个空间
	newnode->data = data;//将数据给新开辟的空间节点
	newnode->next = list->next;//让头节点下一个地址赋给newnode的next指针,也就是newnode的next指针指向第二个节点
    list-> next = newnode;//将头节点的next指针指向node节点
	list->data++;//代表了头节点插入了一个元素
}

尾插法

 将新节点放在链表的最尾端(除了NULL之外)


//尾插法
void tailInsert(Node* list, int data) {

	Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个新空间返回一个地址,新的节点指针newnode指向这个空间

	Node* head = list;//定义一个指针,用来指向头节点

	newnode->data = data;    //将传入的数据域给新节点


	newnode->next = NULL;//新节点指向空
	
	//原链表中最后一个节点的next指向newnode节点

	while (list->next) {//直到list->next为空才跳出,list就代表了原链表最后一个节点
	
		list = list->next;//指针移动
	}
	list->next = newnode;//原链表最后一个元素的指针指向新节点
	
	head->data++;//链表中元素加一

}

删除节点

 直接跳过我们要删除的节点就可以

//删除节点
void Delete(Node* list, int data) {

	Node* pre = list;//用来存储上一个指针,目前是第一个节点,也就是头结点,没有什么含义
	Node* current = list ->next;//用来指向我们要删除节点的指针,目前是除了头节点以外的第二个

	//找到我们需要删除的节点
	while (current) {
		if (current->data == data) {

			pre->next = current->next;//当前节点的上一个节点的指针指向,current下一个节点,跳过了current节点
			/*补充一点基础,我们pre指针指向某个空间以后,就可以对空间进行操作了,上面的意思是把第三个节点的地址覆盖到第一个节点的指针变量上去,*/

			free(current);//释放当前要删除的节点的空间
			/*我们不需要知道要删除空间的具体名字,我们只要知道她的地址就可以,把地址存到一个变量current里面,然后对空间进行操作*/
			break;//跳出循环,要删除多个的话就不break继续删除

		}
		//将两个指针都往后移一个
		pre = current;//我们之前的pre指针是指向链表的头部,后面这样慢慢移动
		current = current->next;
	}
	
	list->data++;//链表中元素加一
}

demo

//传入头结点就相当于传入整个链表,我们可以通过头节点来访问带整个链表,链表的首地址就是头节点的地址
//链表起初也是只有一个节点,后续慢慢添加节点,就变成了一根链

#include<stdio.h>
#include<stdlib.h>
//创建节点的结构体
typedef struct Node {
	int data;//数据
	struct Node* next;//定义一个Node类型结构体类型的指针

}; Node;//将struct Node 命名为Node,简化操作

//初始化头结点
Node* initList() {
	Node* list = (Node*)malloc(sizeof(Node));//左边创建一个Node类型的指针list,右边开辟一个空间然后返回一个空间的地址指针,这样list指针指向新开辟的空间,
	/*malloc(sizeof(Node))开辟一个Node大小的空间内存,(Node*)表示的是类型转换为Node类型的指针*/

	list->data = 0;
	list->next = NULL;
	return list;//返回头节点
}

//头插法
// 把地址给那个变量,就是让那个指针变量指向自己
// 注意左边是指针,右边是地址
//传入头节点、数据域
void headInsert(Node* list, int data) {
    
	Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个空间返回一个地址,新的节点指针newnode指向这个空间
	newnode->data = data;//将数据给新开辟的空间节点
	newnode->next = list->next;//让头节点下一个地址赋给newnode的前驱指针
    list-> next = newnode;//将头节点的next指针指向newnode节点
	list->data++;//代表了头节点插入了一个元素
}

//尾插法
void tailInsert(Node* list, int data) {

	Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个空间返回一个地址,新的节点指针node指向这个空间

	Node* head = list;//定义一个头节点

	newnode->data = data;    //将传入的数据域给新节点


	newnode->next = NULL;//新节点指向空
	
	//原链表中最后一个节点的next指向node节点

	while (list->next) {//直到list->next为空才跳出,list就代表了原链表最后一个节点
	
		list = list->next;
	}
	list->next = newnode;//原链表最后一个元素的指针指向新节点
	
	head->data++;//链表中元素加一

}
                        
 //删除节点
void Delete(Node* list, int data) {

	Node* pre = list;//用来存储上一个指针,目前是第一个节点,也就是头结点,没有什么含义
	Node* current = list ->next;//用来指向我们要删除节点的指针,目前是除了头节点以外的第二个

	//找到我们需要删除的节点
	while (current) {
		if (current->data == data) {

			pre->next = current->next;//当前节点的上一个节点的指针指向,current下一个节点,跳过了current节点
			/*补充一点基础,我们pre指针指向某个空间以后,就可以对空间进行操作了,上面的意思是把第三个节点的地址覆盖到第一个节点的指针变量上去,*/

			free(current);//释放当前要删除的节点的空间
			/*我们不需要知道要删除空间的具体名字,我们只要知道她的地址就可以,把地址存到一个变量current里面,然后对空间进行操作*/
			break;//跳出循环,要删除多个的话就不break继续删除

		}
		//将两个指针都往后移一个
		pre = current;//我们之前的pre指针是指向链表的头部,后面这样慢慢移动
		current = current->next;
	}
	
	list->data++;//链表中元素加一
}

//遍历节点
void printlist(Node* list) {

	list = list->next;//跳过了头结点
	while (list) {
		printf("%d", list->data);
		list = list->next;//list下移
	}

	printf("\n");

}



int main(void)
{
	Node* list = initList();//初始化一个list链表

	headInsert(list, 1);
	headInsert(list, 2);
	headInsert(list, 3);
	headInsert(list, 4);
	headInsert(list, 5);

	tailInsert(list, 6);
	tailInsert(list, 7);
	tailInsert(list, 8);
	tailInsert(list, 9);
	tailInsert(list, 10);


	//删除
	Delete(list, 10);

	printlist(list);
	return 0;
}

双链表

 一个模块都是一个节点,也就是一个结构体,里面存放了二个指针变量(pre和next)和一个data变量,最后一个节点值指向空

头插法

 注意:这里一个特殊情况就是插入之后,是一个null,null无法向前指向,这样只有三根箭头,看下面的代码

//头插法
void headInsert(Node* list, int data) {

	Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个空间存放newnode节点
	newnode->data = data;
	newnode->pre = list;//新节点前指针指向头节点
	newnode->next = list->next;//新节点的next指针指向第二个节点
	//下面是考虑空节点的情况
	if (list->next)//list第二个节点不是空的
	{
		list->next->pre = newnode;//第二个节点的pre指针指向newnode
		list->next = newnode;//第一个节点的next指针指向node
	}
	else //list第二个节点是null
		list->next = newnode;//指针下移
	
}

尾插法


//尾插法
void tailInsert(Node* list, int data) {

	Node* node = list;//创建一个指针node来追踪尾部节点(除去null)
	Node* newnode = (Node*)malloc(sizeof(Node));//创建一个空间给新节点

	newnode->data = data;
	while (node->next)//node指针指向最后一个节点

	{
		node = node->next;//node节点下移
	}

	newnode->next = node->next;//新节点的next指针指向尾结点的下一个节点,也就是NULL
	node->next = newnode;//
	newnode->pre = node;//新节点的pre指向最后一个节点
	list->data++;
}

删除节点-

注意:这里有一种特殊情况,就是右边的节点是null,就只有三根线


int Delete(Node * list, int data) {
	Node* node = list->next;//创建一个指针变量指向要删除的节点
	while (node) {
		if (node->data == data) {
			//删除节点 下面有一种删除最后一个元素的	情况
			if (node->next != NULL) {
				node->pre->next = node->next;//要删除的节点的前一个节点的next指针指向要删除节点的下一个节点
				node->next->pre = node->pre;//要删除的节点的下一个节点的pre指针指向要删除节点的上一个节点
				free(node);
				list->data--;
			}
			else {
			node->pre->next = NULL;//要删除节点的前一个节点的后继指针指向空
				free(node);
				list->data--;
			}
			return TRUE;

		}
		node = node->next;//指针移动
	}
	return FALSE;

}

demo



#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
//双链表要考虑NULL的情况,因为双链表要礼尚往来你指我,我也要指你,但NULL无法指向别人
typedef struct Node {

	int data;

	struct Node* pre;
	struct Node* next;
}Node;//将struct Node重新命名为Node
//链表的初始化
Node* initList() {
	Node* list = (Node*)malloc(sizeof(Node));//开辟空间给头节点
	list ->data = 0;
    list ->next = NULL;
    list ->pre = NULL;

	return list;//初始化完毕返回结果
}


//头插法
void headInsert(Node* list, int data) {

	Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个空间存放newnode节点
	newnode->data = data;
	newnode->pre = list;//新节点前指针指向头节点
	newnode->next = list->next;//新节点的next指针指向第二个节点
	//下面是考虑空节点的情况
	if (list->next)//list第二个节点不是空的
	{
		list->next->pre = newnode;//第二个节点的pre指针指向newnode
		list->next = newnode;//第一个节点的next指针指向node
	}
	else //list第二个节点是null
		list->next = newnode;//指针下移
	
}

	

//尾插法
void tailInsert(Node* list, int data) {

	Node* node = list;//创建一个指针node来追踪尾部节点(除去null)
	Node* newnode = (Node*)malloc(sizeof(Node));//创建一个空间给新节点

	newnode->data = data;
	while (node->next)//node指针指向最后一个节点

	{
		node = node->next;//node节点下移
	}

	newnode->next = node->next;//新节点的next指针指向尾结点的下一个节点,也就是NULL
	node->next = newnode;//
	newnode->pre = node;//新节点的pre指向最后一个节点
	list->data++;
}
//删除节点



int Delete(Node * list, int data) {
	Node* node = list->next;//创建一个指针变量指向要删除的节点
	while (node) {
		if (node->data == data) {
			//删除节点 下面有一种删除最后一个元素的	情况
			if (node->next != NULL) {
				node->pre->next = node->next;//要删除的节点的前一个节点的next指针指向要删除节点的下一个节点
				node->next->pre = node->pre;//要删除的节点的下一个节点的pre指针指向要删除节点的上一个节点
				free(node);
				list->data--;
			}
			else {
			node->pre->next = NULL;//要删除节点的前一个节点的后继指针指向空
				free(node);
				list->data--;
			}
			return TRUE;

		}
		node = node->next;//指针移动
	}
	return FALSE;

}


//打印出链表的信息
void printList(Node* list)
{
    Node* node = list->next;
	while (node) 
	{
		printf("%d ", node->data);
		node = node->next;
	}
}
int main() {
	Node* list = initList();//创建出了一个头节点list,后面以这个为基础扩展
	headInsert(list, 1);
	headInsert(list, 2);
	headInsert(list, 3);
	headInsert(list, 4);
	tailInsert(list, 5);
	tailInsert(list, 6);
	tailInsert(list, 7);
	tailInsert(list, 8);
	Delete(list,8);
	printList(list);
	return 0;
}

单向循环链表

头插法


//头插法
void headInsert(Node* list, int data) {
 
	Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个空间给新节点
	newnode ->data = data;
	newnode ->next = list->next;//右边存放指针变量存放了第二个节点的地址,覆盖到新节点的指针变量上去,这样的话新节点就可以指向list链表的第二个节点
	list->next = newnode;//将新节点地址给list链表的第一个节点的指针,这样L链表就会指向newnode新节点
	list->data++;
}

尾插法


//尾插法
void tailInsert(Node* list, int data) {
	Node* n = list;//n指针用来指向链表最后一个节点,目前是指向头节点

	Node* newnode= (Node*)malloc(sizeof(Node));//开辟一个空间给新节点
	newnode->data = data;
	//将n指针变量移动一直到移动到指向最后一个节点,标志是下一个就是头结点
	while (n->next != list) {
	
		n = n->next;//指针下移

	}

	newnode ->next = list; //newnode节点指向头结点
	n->next = newnode;//旧链表最后一个节点指向新节点
	list ->data++;//节点增加一个

删除节点


//*删除
int Delete(Node* list, int data)
{
	/*pre节点起初是指向头节点,node节点指向下一个节点,因为指针一直在移动等我们找到要删除的节点pre指针指向要删除节点的前一个节点位置*/
	Node* prenode = list;//前一个节点的指针
	Node* currentnode = list->next;  //新建一个指针currentnode,用来追踪我们要删除的节点
	//找要删除的节点,这个要重头遍历到尾部
	while (currentnode!= list)
	{
		if (currentnode->data == data)
		{
			//delete
			prenode->next = currentnode->next;//前项指针变量移动到我们目标之后,我们直接跳过了要删除的节点
			free(currentnode);
			list->data--;
			return TRUE;
		}
		prenode = currentnode;//pre指针移动
		currentnode = currentnode->next;//指针移动
		
	}
	re

demo

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
 typedef struct Node {
	int data;
	struct Node* next;
}Node;//将struct Node 重新,命名为Node

Node* initList() {
	Node* list = (Node*)malloc(sizeof(Node));//开辟一个空间将地址赋给指针L
    
	list-> data = 0;
	list-> next = list;//指向自己
	return list;
}

//头插法
void headInsert(Node* list, int data) {
 
	Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个空间给新节点
	newnode ->data = data;
	newnode ->next = list->next;//右边存放指针变量存放了第二个节点的地址,覆盖到新节点的指针变量上去,这样的话新节点就可以指向list链表的第二个节点
	list->next = newnode;//将新节点地址给list链表的第一个节点的指针,这样L链表就会指向newnode新节点
	list->data++;
}


//尾插法
void tailInsert(Node* list, int data) {
	Node* n = list;//n指针用来指向链表最后一个节点,目前是指向头节点

	Node* newnode= (Node*)malloc(sizeof(Node));//开辟一个空间给新节点
	newnode->data = data;
	//将n指针变量移动一直到移动到指向最后一个节点,标志是下一个就是头结点
	while (n->next != list) {
	
		n = n->next;//指针下移

	}

	newnode ->next = list; //newnode节点指向头结点
	n->next = newnode;//旧链表最后一个节点指向新节点
	list ->data++;//节点增加一个

}
//遍历链表
void printList(Node* list) {
    
	Node* node = list->next;//创建一个指针变量来遍历

	while (node != list) {
		printf("%d", node->data);
		node = node->next;//node指针指向下一个节点空间
	}

}

//*删除
int Delete(Node* list, int data)
{
	/*pre节点起初是指向头节点,node节点指向下一个节点,因为指针一直在移动等我们找到要删除的节点pre指针指向要删除节点的前一个节点位置*/
	Node* prenode = list;//前一个节点的指针
	Node* currentnode = list->next;  //新建一个指针currentnode,用来追踪我们要删除的节点
	//找要删除的节点,这个要重头遍历到尾部
	while (currentnode!= list)
	{
		if (currentnode->data == data)
		{
			//delete
			prenode->next = currentnode->next;//前项指针变量移动到我们目标之后,我们直接跳过了要删除的节点
			free(currentnode);
			list->data--;
			return TRUE;
		}
		prenode = currentnode;//pre指针移动
		currentnode = currentnode->next;//指针移动
		
	}
	return FALSE;
}
                                         
int main(void)
{
	Node* list = initList();//初始化一个list链表

	headInsert(list, 1);
	headInsert(list, 2);
	headInsert(list, 3);
	headInsert(list, 4);
	headInsert(list, 5);
	tailInsert(list, 6);
	tailInsert(list, 7);
	tailInsert(list, 8);
	tailInsert(list, 9);
	tailInsert(list, 10);
	Delete(list, 10);

	printList(list);
	return 0;
}

双向循环链表

头插法

void headInsert(Node* L, int data) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    node->next = L->next;
    node->pre = L;
    L->next->pre = node;
    L->next = node;
    L->data++;
}

尾插法

void tailInsert(Node* L, int data) {
    Node* node = L;
    while (node->next != L) {
        node = node->next;
    }
    Node* n = (Node*)malloc(sizeof(Node));
    n->data = data;
    n->pre = node;
    n->next = L;
    L->pre = n;
    node->next = n;
    L->data++;
}

删除节点

int delete (Node* L, int data) {
    Node* node = L->next;
    while (node != L) {
        if (node->data == data) {
            node->pre->next = node->next;
            node->next->pre = node->pre;
            free(node);
            L->data--;
            return 1;
        }
        node = node->next;
    }
    return 0;
}

demo

/**
 * File Name: LoopDoubleLinkList.c
 * Author: tyrantlucifer
 * E-mail: tyrantlucifer@gmail.com
 * Blog: https://tyrantlucifer.com
 */
#include <stdio.h>
#include <stdlib.h>

/**
 * define the struct of list node
 */
typedef struct Node {
    int data;
    struct Node* pre;
    struct Node* next;
} Node;

/**
 * init a link list
 * @return the head pointer of link list's head
 */
Node* initList() {
    Node* L = (Node*)malloc(sizeof(Node));
    L->data = 0;
    L->pre = L;
    L->next = L;
    return L;
}

/**
 * insert item in link list's head
 * @param L the head pointer of link list
 * @param data  the data you want to insert
 */
void headInsert(Node* L, int data) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    node->next = L->next;
    node->pre = L;
    L->next->pre = node;
    L->next = node;
    L->data++;
}

/**
 * insert item in link list's tail
 * @param L the head pointer of link list
 * @param data the data you want to insert
 */
void tailInsert(Node* L, int data) {
    Node* node = L;
    while (node->next != L) {
        node = node->next;
    }
    Node* n = (Node*)malloc(sizeof(Node));
    n->data = data;
    n->pre = node;
    n->next = L;
    L->pre = n;
    node->next = n;
    L->data++;
}

/**
 * delete item in link list
 * @param L the head pointer of link list
 * @param data the data you want to delete
 * @return success flag
 */
int delete (Node* L, int data) {
    Node* node = L->next;
    while (node != L) {
        if (node->data == data) {
            node->pre->next = node->next;
            node->next->pre = node->pre;
            free(node);
            L->data--;
            return 1;
        }
        node = node->next;
    }
    return 0;
}

/**
 * print all items in a link list
 * @param L the head pointer of link list
 */
void printList(Node* L) {
    Node* node = L->next;
    while (node != L) {
        printf("%d -> ", node->data);
        node = node->next;
    }
    printf("NULL\n");
}

/**
 * main function
 * @return null
 */
int main() {
    Node* L = initList();
    headInsert(L, 1);
    headInsert(L, 2);
    headInsert(L, 4);
    headInsert(L, 5);
    printList(L);
    tailInsert(L, 6);
    tailInsert(L, 7);
    printList(L);
    delete (L, 7);
    printList(L);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值