设计链表的实现。

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

public class MyLinkedList {
	/**
	 * 链表头:一个虚拟的链表头,用来表示链表的头部,用于链接其他节点。所有其它节点的增删操作都不会影响该链表头的地位。该链表头在链表中的角标设计为-1.
	 * 		实际链表数据依然从角标0开始。
	 */
	private Node head;
	/**
	 * 链表数据大小:表示当前链表数据容量大小个数。默认初始化为0
	 */
	private int size;
	/**
	 *  初始化单链表,创建虚拟头节点
	 */
	public MyLinkedList() {
		this.head = new Node(null, 0);
	}
	/**
	 * 通过角标来获取指定角标节点的值。
	 * @param index  指定的角标值
	 * @return	返回指定角标元素节点数据的值(Node element)
	 */
	public int get(int index) {
		if(index < 0) {
			return -1;
		}
		Node node = node(index);
		return node.element;
	}
	/**
	 * 根据传入的数据值,创建一个节点(Node),并将该节点放在链表的头部(即虚拟头节点的下一个节点,也即是实际上的第一个节点)
	 * @param val 传入的数据值
	 */
	public void addAtHead(int val) {
		/* 根据传入的数据值,创建一个无链接的新节点(Node next值为null)*/
		Node newNode = new Node(null, val);
		/* 如果链表中已存在节点,通过虚拟头节点head来获取原第一个节点 */
		if(size > 0) {
			Node originalFirstNode = head.next;	
			/* 将无链接的新节点的下一个节点指向原第一个节点 */
			newNode = new Node(originalFirstNode, val);
		}
		/* 虚拟头节点的下一个节点指向新节点 */
		head.next = newNode;
		/* 链表数据+1 */
		size++;
	}
	/**
	 * 根据传入的数据值,创建一个节点(Node),并将该节点放在链表的尾部
	 * @param val
	 */
	public void addAtTail(int val) {
		/* 根据传入的数据值,创建一个无链接的新节点(Node next值为null)*/
		Node newNode = new Node(null, val);
		/* 获取尾节点 */
		Node tailNode = node(size-1);
		/* 设置尾节点的下一个节点为当前新节点*/
		tailNode.next = newNode;
		/* 链表数据+1 */
		size++;
	}
	/**
	 * 在链表指定的角标索引下的节点的前面插入一个指定数据值为 val的新节点
	 * @param index  指定的角标值
	 * @param val 传入的数据值
	 */
	public void addAtIndex(int index, int val) {
		/* 如果index大于链表大小,不做操作 */
		if(index > size||index < 0) {
			return;
			/* 如果角标索引为0,或者链表中数据大小为0,则插入到头部 */
		}else if(index == 0||size == 0) {
			addAtHead(val);
			return;
			/* 如果index == size 则插入到尾部(因为最后一个节点(尾部节点)的角标为 size-1) */
		}else if(index == size) {
			addAtTail(val);
			return;
		}else {
			/*	否则说明当前插入点介于两个节点之间
			 *	1  获取到要插入节点的前一个节点
			 *	2  获取要插入在其前面的当前节点
			 *	3  创建新节点 将该新节点的下一个节点指向 2 中节点
			 *	4  将1中节点的下一个节点指向我们要插入的新节点
			 *	5 size+1
			 */
			Node insertBeforePreNode = node(index-1);
			Node insertBeforeNode = insertBeforePreNode.next;
			Node newNode = new Node(insertBeforeNode, val);
			insertBeforePreNode.next =newNode;
			size++;
		}
	}
	/**
	 * 删除指定角标索引下的节点
	 * @param index
	 */
	public void deleteAtIndex(int index) {
		/* 如果当前角标大于或等与size,什么都不做
		 * 1  链表为空时,size = 0 = index,不需要删除
		 * 2  最后一个节点(尾部节点)的角标为 size-1 ,不需要删除
		 * */
		if(index >= size||index < 0) {
			return;
		}
		
		//以下建立在size>0前提条件下
		
		/* 获取当前角标索引的前一个节点。如果index为0,则获取到虚拟头节点 */
		Node preNode = node(index-1);
		/* 获取要删除的当前节点 */
		Node curNode = preNode.next;
		/* 获取下一个节点 */
		Node nextNode = curNode.next;
		/* 如果要删除的当前节点的下一个节点为空,则不需要将该节点的前一个节点指向该节点的下一个节点 */
		if(nextNode == null) {
			preNode.next = null;
		}else {
			/* 否则,将该节点的前一个节点指向该节点的下一个节点 */
			preNode.next = nextNode;
		}
		/* size -1 */
		size--;
	}
	/**
	 * 返回指定角标下的节点。从0---index(index<size),即index范围是从0---size-1
	 * @param index  
	 * @return
	 */
	private Node node(int index) {
		if(index == -1){
			return head;
		}
		Node next = head.next;//0号角标节点
		if(index < size) {
			for (int i = 1; i <= index; i++) {
				next = next.next;
			}
		}else {
			//如果index小于0且不等于-1 返回 val为-1 的节点
			return new Node(null, -1);
		}
		return next;
	}
	
	public int size() {
		return size;
	}
	
	public class Node {
		 public Node next;

		 public int element;

		public Node(MyLinkedList.Node node, int element) {
			super();
			this.next = node;
			this.element = element;
		}
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴回答你关于C语言课程设计的问题!链表是一种常用的数据结构,可以用来实现学生信息管理系统。下面是一个简单的示例代码,实现了学生信息的添加、查找和删除功能: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct student { char name[50]; int age; struct student* next; } Student; Student* createStudent(char name[], int age) { Student* newStudent = (Student*)malloc(sizeof(Student)); strcpy(newStudent->name, name); newStudent->age = age; newStudent->next = NULL; return newStudent; } void addStudent(Student** head, char name[], int age) { Student* newStudent = createStudent(name, age); if (*head == NULL) { *head = newStudent; } else { Student* temp = *head; while (temp->next != NULL) { temp = temp->next; } temp->next = newStudent; } printf("学生 %s 添加成功\n", name); } void findStudent(Student* head, char name[]) { if (head == NULL) { printf("学生信息为空\n"); return; } Student* temp = head; while (temp != NULL) { if (strcmp(temp->name, name) == 0) { printf("找到学生 %s,年龄:%d\n", name, temp->age); return; } temp = temp->next; } printf("未找到学生 %s\n", name); } void deleteStudent(Student** head, char name[]) { if (*head == NULL) { printf("学生信息为空\n"); return; } Student* temp = *head; Student* prev = NULL; while (temp != NULL) { if (strcmp(temp->name, name) == 0) { if (prev == NULL) { *head = temp->next; } else { prev->next = temp->next; } free(temp); printf("删除学生 %s 成功\n", name); return; } prev = temp; temp = temp->next; } printf("未找到学生 %s\n", name); } void printStudents(Student* head) { if (head == NULL) { printf("学生信息为空\n"); return; } printf("学生信息列表:\n"); Student* temp = head; while (temp != NULL) { printf("姓名:%s,年龄:%d\n", temp->name, temp->age); temp = temp->next; } } void destroyStudents(Student** head) { if (*head == NULL) { return; } Student* current = *head; Student* next; while (current != NULL) { next = current->next; free(current); current = next; } *head = NULL; printf("释放学生信息成功\n"); } int main() { Student* head = NULL; addStudent(&head, "张三", 20); addStudent(&head, "李四", 21); addStudent(&head, "王五", 22); printStudents(head); findStudent(head, "李四"); findStudent(head, "赵六"); deleteStudent(&head, "李四"); printStudents(head); destroyStudents(&head); return 0; } ``` 这个例子中,我们定义了一个`Student`结构体,包含学生的姓名和年龄,并且有一个指向下一个学生的指针。我们可以使用`createStudent`函数创建一个新的学生节点,然后用`addStudent`函数将学生添加到链表中。`findStudent`函数用于查找指定姓名的学生,`deleteStudent`函数用于删除指定姓名的学生,`printStudents`函数用于打印所有学生信息,`destroyStudents`函数用于释放链表内存。 希望这个示例能够帮助你开始实现学生信息管理系统!如果你有任何问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值