单链表详解及其基本操作【C&Java】

个人主页Hello Code.
本文专栏数据结构
如有问题,欢迎指正,一起学习~~

目录

概述

基本操作

初始化链表

创建

代码实现

C语言

Java


概述

链表是一种在物理存储单元上非连续、非顺序的一种数据的存储结构。由一系列结点组成,结点可以在运行时动态生成。

链表主要可分为单链表双链表循环链表等。本文主要就做一下单链表的基本操作展示,其他的大家可以去自行研究。

单链表中每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

一般还会有head(头结点)、end(尾节点)以及p(临时指针)来帮助我们完成链表的一些基本操作

在上图中,N1称为头结点,N3为尾结点;N1是N2的前驱结点,N2是N1的后继结点

特点

  1. 长度可变
  2. n个结点离散分配
  3. 每一个结点通过指针连接
  4. 每个节点都有前驱和后继(头结点无前驱,尾结点无后继)

基本操作

在对数据的操作中,最常见的就是增、删、改、查以及排序操作

本文会通过JavaC两种语言来对单链表进行代码展示


初始化链表

链表中每个结点对应的都是在内存中开辟的一处空间,它分为数据域指针域两部分

c语言中使用malloc开辟,Java中则是通过new来开辟空间

在初始化的时候,就是开辟一处空间,将地址给head结点,因为初始化时没有其他结点,所以也需要将指针域赋值为NULL

创建

在创建一个链表时,通过输入链表的结点个数,用for循环进行遍历,依次开辟各个空间并对每个结点的数据域和指针域赋值后,用指针将各个结点连接起来,就可以完成链表的创建工作,形成一个链表结构

在链表中增加元素,首先需要在内存中开辟一个空间作为新结点并赋值,找到需要添加的位置的前驱结点,让该结点断开原链接,指向被添加结点,再让被添加结点指向原后继结点即可完成。(若有头结点,则头插法和按位置插入类似;尾插法则不需要断开链接,直接让end指向新结点即可)

链表中元素的删除,首先需要遍历链表找到需要删除的结点的前驱结点,并让该结点直接指向被删结点的后继,就是通过跳过要删除的结点来实现删除操作。最后,在C语言中还应通过free()来释放掉被删除结点所开辟的内存空间,防止空间的浪费。

Java中不用free释放空间是因为Java具有垃圾回收机制,会在空闲时间自动处理

 改

链表中结点的修改其实很简单,只需要通过遍历找到要修改的结点位置,然后直接给该结点赋上需要修改的值覆盖掉旧值即可

在遍历链表时,首先定义一个临时指针p指向head,然后通过不断地后移p指针(p=p->next),即可完成链表的遍历。查找各个结点在前几步操作中都有体现,这里就不做动图展示了,原理也不难,很容易理解

遍历指依次获取到每个结点,但并不是说遍历就是将数据都打印出来,获取到每个结点后可以进行各种操作,而不仅仅是打印。但在本文中,为了更直观的展示数据,遍历后的操作就定为打印


代码实现

在代码实现部分,将通过C和Java两种语言进行,代码如下:

C语言

1.头文件

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

typedef int DataType;

2.链表结点结构

typedef struct{
    DataType data;
    struct LinkList *next;
}LinkList;

3.初始化

LinkList *InitList(){
	LinkList *head;
	head = (LinkList*)malloc(sizeof(LinkList));
	head->next = NULL;
	return head;
}

4.创建

void CreateList(LinkList *head, int n){
	LinkList *end, *node;
	DataType data;
	int i;
	end = head;
	for(i = 0; i < n; i++){
		node = (LinkList*)malloc(sizeof(LinkList));
		printf("请输入结点数据:");
		scanf("%d",&data);
		node->data = data;
		node->next = NULL;
		end->next = node;
		end = node;
	}
	printf("创建成功!\n");
}

5.增

void ListInsert(LinkList *head, int n){		// n表示需要添加的结点位置
	LinkList *node, *p;
	DataType data;
	int m;
	int length = ListLength(head);
	p = head;
	m = 0;
	if(n <= (length + 1) && n >= 0){
		while(p != NULL){
			if(m == n - 1) break;
			else{
				p = p->next;
				m++;
			}
		}
		node = (LinkList*)malloc(sizeof(LinkList));
		printf("请输入要插入结点的数据:");
		scanf("%d",&data);
		node->data = data;
		node->next = p->next;
		p->next = node;
		printf("添加成功!\n");
	}
	else printf("插入位置错误,请重新输入!\n");
}

6.删

void ListDelete(LinkList *head,int n){
	LinkList *q, *p;
	int m = 0;
	p = head;
	while(m < n && p != NULL){
		q = p;
		p = p->next;
		m++;
	}
	if(p != NULL){
		q->next = p->next;
		free(p);
        printf("删除成功!\n");
	}
	else printf("该结点不存在,请重新输入!\n");
}

7.改

void ListChange(LinkList *head,int n){
	LinkList *p;
	DataType data;
	int i = 0;
	p = head;
	while(i < n && p != NULL){
		p = p->next;
		i++;
	}
	if(p != NULL){
		printf("请输入您要修改的值:");
		scanf("%d",&data);
		printf("%d已成功修改为%d\n",p->data,data);
		p->data = data;
	}else{
		printf("结点不存在!\n");
	}
}

8.查

void ListTraverse(LinkList *head){
	LinkList *p = head->next;
	printf("您存储的数据为:");
	while(p != NULL){
		printf("%d ",p->data);
		p = p->next;
	}
	printf("\n");
}

main

main(){
	LinkList *head;
	int choice = 0;
	int n;
	head = NULL;
	while(choice != 6){
		printf("-----------链表的基本操作-----------\n");
		printf("   1.初始化                         \n");
		printf("   2.增                             \n");
		printf("   3.删                             \n");
		printf("   4.改                             \n");
		printf("   5.查                             \n");
		printf("   6.退出                           \n");
		printf("------------------------------------\n");
		printf("请输入你的选择:");
		scanf("%d",&choice);
		switch(choice){
			case 1:
				head = InitList();
				printf("初始化成功!\n");
				break;
			case 2:
				if(head == NULL) printf("未初始化,请初始化后再进行操作\n");
				else{
					printf("请输入您要增加的结点数量:");
					scanf("%d",&n);
					ListInsert(head,n);
				}
				break;
			case 3:
				if(head == NULL) printf("未初始化,请初始化后再进行操作\n");
				else{
					printf("请输入您要删除的结点:");
					scanf("%d",&n);
					ListDelete(head,n);
				}
				break;
			case 4:
				if(head == NULL) printf("未初始化,请初始化后再进行操作\n");
				else{
					printf("请输入您要修改的结点:");
					scanf("%d",&n);
					ListChange(head,n);
				}
				break;
			case 5:
				ListTraverse(head);
				break;
			case 6:
				printf("退出成功,感谢您的使用!\n");
				break;
		}
	}
}

Java

1.链表结点

private class Node{
	public T data;
	public Node next;		// 指向下一个结点
	
	public Node(T t){
		this(t, null);
	}
	public Node(T t, Node next){
		this.data = t;
		this.next = next;
	}
	public void set(T t){
		this.data = t;
	}
}

2.增

public void addFirst(T t){        // 头插法
		Node node = new Node(t);
		node.next = this.head;
		this.head = node;
		this.size++;
}
public void add(T t, int index){        // 指定位置插入
    if(index < 0 || index > this.size){
        throw new IllegalArgumentException("index is error");
	}
	if(index == 0){
		addFirst(t);
		return;
	}
	Node preNode = this.head;
	for(int i = 0; i < index - 1; i++){
		preNode = preNode.next;
	}
	Node node = new Node(t);
	node.next = preNode.next;
	preNode.next = node;
	this.size++;
}
public void addLast(T t){        // 尾插法
    add(t, this.size);
}

 3.删

public T remove(int index){        // 指定索引删除
	if(index < 0 || index > this.size - 1){
		throw new IllegalArgumentException("index is error");
	}
	T data = null;
	if(index == 0){
		data = head.data;
		this.head = head.next;
		this.size--;
		return data;
	}
	Node preNode = this.head;
	for(int i = 0; i < index - 1; i++){
		preNode = preNode.next;
	}
	Node p = preNode.next;
	data = p.data;
	preNode.next = p.next;
	this.size--;
    return data;
}

public void remove(T t){        // 指定内容删除
	int index = getIndex(t);
	remove(index);
}

4.改

public T set(int index, T t){
	Node p = this.head;
   	for(int i = 0; i < index; i++){
		p = p.next;
	}
	T oldData = p.data;
	p.set(t);
	return oldData;
}

5.查

public boolean contains(T t){        // 查询该元素是否存在
	Node p = this.head;
	while(p != null){
		if(p.data.equals(t)) return true;
		p = p.next;
	}
	return false;
}
public int getIndex(T t){        // 查询指定元素对应索引
	Node p = this.head;
	for(int i = 0; i < this.size; i++){
		T data = p.data;
		if(data.equals(t)) return i;
		else p = p.next;
	}
	return -1;
}

6.遍历

public void display(){
	Node p = this.head;
	while(p != null){
		System.out.println(p.data);
		p = p.next;
	}
}

完整代码
 

package LinkList;

public class LinkedList <T>{
	// 链表结点
	private class Node{
		public T data;
		public Node next;		// 指向下一个结点
		
		public Node(T t){
			this(t, null);
		}
		public Node(T t, Node next){
			this.data = t;
			this.next = next;
		}
		public void set(T t){
			this.data = t;
		}
	}
	private Node head;		// 头结点
	private int size;		// 链表元素个数
	
	public LinkedList(){
		this.head = null;
		this.size = 0;
	}
	
	// 增
	
	public void addFirst(T t){
		Node node = new Node(t);
		node.next = this.head;
		this.head = node;
		this.size++;
	}
	public void add(T t, int index){
		if(index < 0 || index > this.size){
			throw new IllegalArgumentException("index is error");
		}
		if(index == 0){
			addFirst(t);
			return;
		}
		Node preNode = this.head;
		for(int i = 0; i < index - 1; i++){
			preNode = preNode.next;
		}
		Node node = new Node(t);
		node.next = preNode.next;
		preNode.next = node;
		this.size++;
	}
	public void addLast(T t){
		add(t, this.size);
	}
	
	// 删
	public T remove(int index){
		if(index < 0 || index > this.size - 1){
			throw new IllegalArgumentException("index is error");
		}
		T data = null;
		if(index == 0){
			data = head.data;
			this.head = head.next;
			this.size--;
			return data;
		}
		Node preNode = this.head;
		for(int i = 0; i < index - 1; i++){
			preNode = preNode.next;
		}
		Node p = preNode.next;
		data = p.data;
		preNode.next = p.next;
		this.size--;
		return data;
	}
	public void remove(T t){
		int index = getIndex(t);
		remove(index);
	}
	// 修改
	
	public T set(int index, T t){
		Node p = this.head;
		for(int i = 0; i < index; i++){
			p = p.next;
		}
		T oldData = p.data;
		p.set(t);
		return oldData;
	}
	// 查
	public boolean contains(T t){
		Node p = this.head;
		while(p != null){
			if(p.data.equals(t)) return true;
			p = p.next;
		}
		return false;
	}
	public int getIndex(T t){
		Node p = this.head;
		for(int i = 0; i < this.size; i++){
			T data = p.data;
			if(data.equals(t)) return i;
			else p = p.next;
		}
		return -1;
	}
	// 遍历
	public void display(){
		Node p = this.head;
		while(p != null){
			System.out.println(p.data);
			p = p.next;
		}
	}
	public static void main(String[] args){
		LinkedList<Integer> list = new LinkedList<>();
		list.addFirst(2);
		list.add(1, 1);
		list.addLast(5);
		list.display();
		System.out.println("-------------");
		list.remove(1);
		list.display();
		System.out.println("-------------");
		list.set(1, 888);
		list.display();
		System.out.println(list.contains(88));
	}
}

猜你喜欢

转载自blog.csdn.net/qq_24980365/article/details/120717216