Detailed explanation of singly linked list and its basic operations [C&Java]

Personal homepage : Hello Code.
This article column : Data structure
If you have any questions, please correct me and learn together~~

content

Overview

Basic operation

Initialize linked list

create

increase

delete

change

check

Code

C language

Java


Overview

A linked list is a non-consecutive, non-sequential data storage structure on a physical storage unit. Consists of a series of nodes that can be dynamically generated at runtime.

Linked list can be divided into singly linked list , double linked list , circular linked list and so on. This article mainly shows the basic operation of the singly linked list, and everyone else can study it by themselves.

Each node in the singly linked list consists of two parts: one is the data field that stores the data element, and the other is the pointer field that stores the address of the next node .

Generally, there will also be head (head node), end (tail node) and p (temporary pointer) to help us complete some basic operations of the linked list

In the above figure, N1 is called the head node, N3 is the tail node; N1 is the predecessor node of N2, and N2 is the successor node of N1.

Features

  1. variable length
  2. Discrete assignment of n nodes
  3. Each node is connected by a pointer
  4. Each node has predecessors and successors (the head node has no predecessor, and the tail node has no successor)

Basic operation

Among the operations on data, the most common operations are addition, deletion, modification, search and sorting.

This article will show the code of the singly linked list in Java and C.


Initialize linked list

Each node in the linked list corresponds to a space opened up in memory, which is divided into two parts : the data field and the pointer field

In c language, malloc is used to open up, and in Java, new space is used to open up space.

When initializing, it is to open up a space and give the address to the head node. Because there are no other nodes during initialization, it is also necessary to assign the pointer field to NULL.

create

When creating a linked list, by entering the number of nodes in the linked list, traversing it with a for loop, opening up each space in turn and assigning values ​​to the data field and pointer field of each node, and connecting each node with a pointer, then The creation of the linked list can be completed to form a linked list structure

increase

To add an element to the linked list, you first need to open up a space in memory as a new node and assign a value, find the predecessor node of the position to be added, let the node disconnect the original link, point to the added node, and then let the added node be added. The node points to the original successor node to complete. (If there is a head node, the head insertion method is similar to the position insertion method; the tail insertion method does not need to disconnect the link, just let the end point to the new node directly)

 

delete

To delete an element in a linked list, firstly, it is necessary to traverse the linked list to find the predecessor node of the node to be deleted, and let the node directly point to the successor of the deleted node, which is to realize the deletion operation by skipping the node to be deleted. Finally, in the C language, the memory space opened up by the deleted node should be released through free() to prevent the waste of space.

Java does not use free to release space because Java has a garbage collection mechanism, which will be automatically processed in idle time

 change

The modification of the nodes in the linked list is actually very simple, you only need to find the position of the node to be modified by traversing, and then directly assign the value to be modified to the node to overwrite the old value.

check

When traversing the linked list, first define a temporary pointer p to point to the head, and then continuously move the p pointer backward (p=p->next) to complete the traversal of the linked list. Finding each node is reflected in the first few steps of operation, so I won't show it here. The principle is not difficult, and it is easy to understand

Traversal refers to obtaining each node in turn, but it does not mean that traversal is to print all the data. After obtaining each node, various operations can be performed, not just printing. But in this article, in order to display the data more intuitively, the operation after traversal is set to print


Code

In the code implementation part, it will be carried out through C and Java languages, the code is as follows:

C language

1. Header file

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

typedef int DataType;

2. Linked list node structure

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

3. Initialization

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

4. Create

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. Increase

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. delete

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. Change

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. Check

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. Linked list node

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. Increase

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. delete

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. Change

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. Check

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. Traverse

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

full code
 

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));
	}
}

Guess you like

Origin blog.csdn.net/qq_24980365/article/details/120717216