链表添加、删除、插入、修改、查找和单链表逆置

链表的5种操作及单链表逆置

鉴于本人对写作真的没有任何兴趣,从小学开始写作文完全是凑字数,写小说也半途而废,所以从这篇文章开始我要放飞自我,怎么开心怎么写,不要严肃,要沙雕。(突然发现居然有人会看我的文章,为了不误人子弟,我决定痛改前非,好好写!!!)

为什么有链表

众所周知,我们平时最爱用数组存储数据,那么为什么还有链表这个东西呢??让我们来看看链表是什么?数组和链表有什么区别。
在这里插入图片描述
数组和链表都可以用来存储数据,但是二者在内存中存储数据的空间形式有很大区别。
数组的存储空间连续的,不可更改的
在这里插入图片描述
但是链表就不同了

在这里插入图片描述
又称
在这里插入图片描述
链表灵活随意的存储方式注定了链表的存储难度远低于数组,他更优秀的地方在于,他的各种操作真的很方便,也就是代码真的很少。
先给大家展示一下链表的样子

链表,有节点和节点间的联系(也就是链表中的那条链子),节点又分数据域和引用域,数据域用来存储链表中的数据,引用域用来记录下一个节点的存储位置(就是那条链子)
在这里插入图片描述
在这里插入图片描述
节点的种类分为,头结点和尾节点,和普通节点,尾节点最后要指向空。

接下来,我将结合代码,像大家讲一下链表各项功能的实现以及链表他到底方便在哪里
在这里插入图片描述

前提所需

在c语言中,链表的实现靠结构体和指针,但是这些东西java里通通没有,通通没有!!所以,用Java怎么实现呢??
我们要用
首先我们来根据链表的特性建两个类(为了大家方便复制代码【虽然我觉得有人疯了才会复制我的代码】,也为了满足我想敲键盘的快感,我会打很多代码的)。
一个是Node类,来封装节点的属性,一个是Linked类,实现链表功能

public class Node<E>{		//这里,我们要用到泛型,因为不知道会存进来什么样的数据
			public E e;		//数据域中的数据
			public Node<E>  next;		//这个就是最重要的那个链,记住下一个节点的位置,就是那个箭头,又称后继
			public Node<E>(){}
			public Node<E>(e){
				this.e=e;
				}
		public class LInked<E>{
		public Node<E>  root;	//声明一个头结点
		public Node<E> tail;	//声明一个尾节点
		int size;	//定义链表的大小
		public Linked(){
			root=new Node<E>();		//实例化头结点
		}

功能一,添加

	将传入的数据加入整个链表的末尾
		public void add(E e){	//传入一个数据
			Node<E> node=new Node<E>(e);	//生成一个以e为数据的节点
			if(root.next==null){		//此时链表为空,只有头结点(头结点内没有数据)
			root.next=node;	//让头结点的后继变为新生成的node这个节点,也就是让root的箭头指向node
			tail=node;	//让新生成的node节点变成尾节点
			size++;		//链表大小加一
			}
			else{
			tail.next=node;		//让尾节点的后继变为node
			tail=node;			//node变成心得尾节点
			size++;
			}

在这里插入图片描述
(在这里我不得不感叹我的数据结构老师真的教的太好了,很可惜人家回去生宝宝了,一定是一个很温柔的宝宝,随妈妈!)
在这里插入图片描述

删除

删除链表中的任意一个节点,并返回删除元素的值

	public E remove(int index){		//传过来一个想删除的位置
		E e=null;	//先声明一个e,设为null
		if(index<0||index>size)	//第一种情况,删除的位置比零小,比链表的长大
			return e;
		else if(index==size-1)	{//第二种情况,删除尾节点
			Node<E> node=new Node<E>(e);	//先生成一个新的节点,用于记录尾节点的值
			e=tail.e;	//获取尾节点的值
			Node<E> periodnode=new Node<E>(e);	//再生成一个节点,用于获取被删节点的前一个节点
			periodnode=getNode(index-1);//获取前一个节点,getNode是返回当前操作的节点,之后给出代码
			periodnode.next=null;//将被删节点的前一个节点的后继设为空,即设为尾节点,原先的尾节点因为没有引用,java自动将其删除
			size--;
			}
			else if(index==0){		//第二种情况,删除第一个节点
			Node<E> node =new Node<E>(e);		//生成一个新的节点,用于记录被删节点的值
			node=getNode(index);		//获取被删节点
			e=node.e;		//获取被删节点的值
			root.next=node.next;	//根节点的后继指向被删节点的后继
			node.next=null;	//被删节点的后继置为null,被java自动删除
			size--;
			return e;
		}else{		//第三种情况,删除任意一个节点
			Node<E> node=new Node<E>(e);		//生成一个节点,用于记录被删节点的值
			node=getNode(index);		//获取被删节点
			Node<E> periodnode=new Node<E>(e);	//在生成一个节点
			periodnode=getNode(index-1);		//获取被删节点的前一个节点
			Node<E> nextnode=new Node<E>(e);		//再生成一个节点
			nextnode=node.next;		//获取被删节点的后一个节点
			e=node.e;		//获取被删节点的值
			periodnode.next=node.next;		//让被删节点的前一个节点的后继指向被删节点的后一个节点,即被删节点的前一个节点的后继指向被删节点的后继,即断开被删节点和前一个节点的联系
			node.next=null;		//被删节点置为空,即断开被删节点和后一个节点的联系
			size--;
			return e;
		}
		}

在这里插入图片描述
在这里插入图片描述

插入

将元素插入到任意一个位置

	public void put(E e,int index){
		if(index!=1){
			Node<E> newnode=new Node<E>(e);     //生成一个新的节点,把他加进去
			Node<E> periodnode=getNode(index-1);	//再生成一个节点,记录想加位置的前一个节点
			Node<E> node=getNode(index);		//再生成一个节点,记录想加位置的节点
			newnode.next=node;		//要加进去的新节点的后继指向已存在的在原位置的节点
			periodnode.next=newnode;	//想加位置的前一个节点的后继指向新节点
				size++;
			}
			else{
				Node<E> newnode=new Node<E>(e); 	//当想加入头结点后,同理
				Node<E> node=getNode(index);
				newnode.next=node;
				root.next=newnode;
				size++;
		}
	}
	

在这里插入图片描述

查找

查找任意一个值

public Node<E> getNode(int index) {      //返回当前要操作的节点
		Node<E> node = root.next;
		for (int i = 0; i < index; i++) {
			node=node.next;
		}
		return node;
	}
	
	public E get(int index){    //一个简单的循环即可
		E e=null;
		Node<E> node=new Node<E>(e);
		node=getNode(index);
		return node.e;
	}

修改

修改任意一个值

public Node<E> getNode(int index) {//返回当前要操作的节点
		Node<E> node = root.next;
		for (int i = 0; i < index; i++) {
			node=node.next;
		}
		return node;
	}
	
	public void change(int index,int a){
		E e=null;
		Node<E> node=new Node<E>(e);
		node=getNode(index);
		node.e=a;
	}

单链表逆置

敲到这里,真心觉得,认真作一篇博客好累。
在这里插入图片描述
接下来就是链表逆置,挺经典的一道题,加油!!!
链表逆置就是把1234567变成7654321。又将是死亡的作图过程。

public void backput(){
		E e=null;
		Node<E> pnode=new Node<E>(e);		//设置一个节点pnode			
		Node<E> qnode=new Node<E>(e);		//设置另一个节点qnode
		pnode=root.next;		//让根节点的后继指向pnode
		root.next=null;		//根节点后继置为空
		while(pnode!=null){		//pnode不空
			qnode=pnode.next;		//pnode的后继指向pnode
			pnode.next=root.next;		//根节点后继指向pnode的后继
			root.next=pnode;		//看图吧
			pnode=qnode;		//看图吧
		}
	}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
代码中还有各位需要注意的index从零取这种小问题,这篇文章到此结束啦
画图真的太死亡了,希望那些点进我的博客的人能对你们有一些用处
啦啦啦啦啦啦,我是哈哈哈哈哈士奇,我们下期再见(应该不会有了吧)!
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是带表头结点单链表的建立、清空、插入删除查找修改逆置和排序运算的C语言实现代码: ``` #include <stdio.h> #include <stdlib.h> // 定义链表结构体 typedef struct Node { int data; struct Node *next; } Node, *LinkedList; // 创建链表 LinkedList createList() { LinkedList head = (LinkedList)malloc(sizeof(Node)); head->next = NULL; return head; } // 清空链表 void clearList(LinkedList head) { Node *p = head->next; while (p != NULL) { Node *temp = p->next; free(p); p = temp; } head->next = NULL; } // 插入节点 void insertNode(LinkedList head, int data, int index) { Node *p = head; int i = 0; while (p != NULL && i < index) { p = p->next; i++; } if (p == NULL || i > index) { printf("插入位置不合法\n"); return; } Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = p->next; p->next = newNode; } // 删除节点 void deleteNode(LinkedList head, int index) { Node *p = head; int i = 0; while (p->next != NULL && i < index) { p = p->next; i++; } if (p->next == NULL || i > index) { printf("删除位置不合法\n"); return; } Node *temp = p->next; p->next = temp->next; free(temp); } // 查找节点 int findNode(LinkedList head, int data) { Node *p = head->next; int i = 0; while (p != NULL) { if (p->data == data) { return i; } p = p->next; i++; } return -1; } // 修改节点 void modifyNode(LinkedList head, int data, int index) { Node *p = head->next; int i = 0; while (p != NULL && i < index) { p = p->next; i++; } if (p == NULL || i > index) { printf("修改位置不合法\n"); return; } p->data = data; } // 链表逆置 void reverseList(LinkedList head) { Node *p = head->next; Node *pre = NULL; while (p != NULL) { Node *temp = p->next; p->next = pre; pre = p; p = temp; } head->next = pre; } // 链表排序 void sortList(LinkedList head) { Node *p = head->next; int len = 0; while (p != NULL) { len++; p = p->next; } for (int i = 0; i < len - 1; i++) { p = head->next; for (int j = 0; j < len - i - 1; j++) { if (p->data > p->next->data) { int temp = p->data; p->data = p->next->data; p->next->data = temp; } p = p->next; } } } // 打印链表 void printList(LinkedList head) { Node *p = head->next; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { LinkedList list = createList(); insertNode(list, 1, 0); insertNode(list, 2, 1); insertNode(list, 3, 2); insertNode(list, 4, 3); printf("原始链表:"); printList(list); deleteNode(list, 2); printf("删除节点后的链表:"); printList(list); modifyNode(list, 5, 1); printf("修改节点后的链表:"); printList(list); reverseList(list); printf("逆置后的链表:"); printList(list); sortList(list); printf("排序后的链表:"); printList(list); clearList(list); printf("清空后的链表:"); printList(list); return 0; } ``` 希望这个代码能够帮到你。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值