数据结构-链表

线性结构的链式存储是用若干地址分散的存储单元存储数据元素,逻辑上相邻的两个数据元素在物理位置上并不一定相邻,必须采用附加信息来表示数据元素之间的顺序关系。因此存储一个数据元素的数据单元至少包含两部分------数据域和地址域
在这里插入图片描述

上述的结构通常称为结点
一个节点表示一个数据元素,通常节点当中的地址会把数据结点连接起来,节点当中的连接关系体现了线性表当中数据元素间的顺序关系,采用这种关系的称为线性链表。
在这里插入图片描述

从上图当中,head是线性链表当中的第一个节点,但是这个节点在数据域当中并没有存储数据,这里之所以写这个的目的是我们能够通过头指针去遍历我们整个链表。
最后一个节点的地址域为空,表示其后不再有节点。每个结点只有一个地址域的链表称为单链表
单链表:该地址域通常指向候机节点; 每个节点有两个地址域的线性表称为双链表
双链表:两个地址域分别指向前驱节点和后继节点。
在这里插入图片描述

在这里插入图片描述

1.定义单链表的节点

public class ListNode  {
	int val;  //定义当前节点的值
	ListNode next; //下一个节点的地址
	//定义一个构造函数
	public ListNode(int value) {
		this.val = value;
	}
}

2.建立单链表

public class Test {
	public static void main(String[] args) {
             //定义一个节点,数据域为 1 ,地址域为 null;
		ListNode node1 = new ListNode(1);   
		//定义一个节点,数据域为2 ,地址域为 null;    
		ListNode node2 = new ListNode(2);  
		//定义一个节点,数据域为 2 ,地址域为 null;
		ListNode node3 = new ListNode(3); 
		
		node1.next = node2;   //node1的地址域为 node2的地址
		node2.next = node3;   //node2的地址域为 node3的地址
		
	}
}

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

3.链表的创建和遍历(头插法和尾插法)

public class LinkList {
	
	//定义链表的头结点
     ListNode head = null;
	

       /**
     * 尾插法添加元素生成链表 
     * @param val 值
     */
	public  void EndInsert(int val) {
		//每次执行这个方法的时候,都要新建路一个节点用来存储数据、
		ListNode listNode = new ListNode(val);
		//判断头特点是否为空,如果是那么将头结点指向新的节点,然后结束
		if (head == null) {
			head = listNode;
			return;
		}
		
		//定义一个临时结点由他的充当指针,指针最开始指向头节点
		ListNode indexNode = listNode;
		//从头结点可是遍历,到最尾部插入
		while (indexNode.next != null) {
			indexNode = indexNode.next;
			
		}
		indexNode.next = listNode;
	}
	
 
 	/**
	 * 头插法添加元素生成链表 
	 * @param val
	 */
	public  void HeadInsert(int val) {
		//每次执行这个方法的时候,都要新建路一个节点用来存储数据、
		ListNode listNode = new ListNode(val);
		//判断头特点是否为空,如果是那么将头结点指向新的节点,然后结束
		if (head == null) {
			head = listNode;
			return;
		}
		
		listNode.next = head;
		head= listNode;
	}
	
	/**
	 * 链表的输出
	 */
	public void printLink() {
		//定义一个临时结点充当指针,从头结点喀什不断想向后移动
		ListNode tempListNode = head;
		
		//将临时结点不断的往后边移动,直到临时结点指向了 null;
		while (tempListNode  !=null) {
			System.out.print(tempListNode.val);
			tempListNode = tempListNode.next;
		}
		System.out.println();
	}
	
	/**
	 * @return  链表的长度
	 */
	public int GetListLenght() {
		//定义一个节点指向该链表
		ListNode tempListNode = head;
		int length = 0;
		while (tempListNode != null) {
			length ++;
			tempListNode = tempListNode.next;
		}
		
		return length;
	}	
}

4.查找某个元素是否在链表的结点上

/**
	 *  查找某个元素是否在链表的结点上
	 * @param val
	 * @return
	 */
	public boolean contains(int val) {
		//定义一个节点指向该链表、
		ListNode tempListNode = head;
		int length = 0;
		while (tempListNode != null) {
			if (tempListNode.val == val) {
				return true;
			}
			tempListNode = tempListNode.next;
		}
		return false;
	}

5.指定位置插入结点
实现思路:先判断插入位置为头尾两端的情况,即index == 0插入到头部,index == size()插入到尾部;如果插入位置不是头尾两端,则先找出当前index位置的结点cur以及前一个结点 pre,然后cur成为新结点的下一个结点,新结点成为pre的后一个结点,这样就成功插入到index位置。

/**
	 *   结点插入至指定位置
	 * @param val   要插入的值
	 * @param index  要插入的位置
	 */
	public void  addNodeAtIndex(int val,int index) {
		//首先判断index的合法性
		if (index<0 || index > GetListLenght()) {
			throw new IndexOutOfBoundsException("index 不合法");
		}
		//如果index = 0,那么就是用头插法
		//如果index = size,那么就是使用尾插法
		if (index == 0) {
			HeadInsert(val);
		}else if (index == GetListLenght()) {
			EndInsert(val);
		}else {
			 //插到某个中间位置
			//每次执行这个方法的时候,都要新建路一个节点用来存储数据、
			ListNode listNode = new ListNode(val);
			//定义一个节点指向该链表、
			ListNode tempListNode = head;
			ListNode pre = null;  //记录前置结点
			//找到相关的位置
			int position =0;
			while(tempListNode != null) {
				//如果位置正确那么就定下来.进行交换
				if (position == index) {
					listNode.next = tempListNode;
					pre.next = listNode;
					return;
				}
				pre = tempListNode;
				tempListNode = tempListNode.next;
				position ++ ;
			}
		}
		
	}

6.删除指定位置结点
实现思路:找出当前index位置的结点cur以及前一个结点 pre,pre.next直接指向cur.next即可删除cur结点。

/**
	 * 删除指定位置结点
	 * @param index
	 */
	public void  deleteNodeAtIndex(int index) {
		//首先判断index的合法性
		if (index<0 || index > GetListLenght()) {
			throw new IndexOutOfBoundsException("index 不合法");
		}
		//如何删除的是头部,那么栈内存直接指向一下个就好了
		if(index == 0) {
			head = head.next;
			return;
		}
		//定义一个节点指向该链表、
		ListNode tempListNode = head;
		ListNode pre = null;  //记录前置结点
		//找到相关的位置
		int position =0;
		while(tempListNode != null) {
			//如果位置正确那么就定下来.进行交换
			if (position == index) {
				pre.next = tempListNode.next;
				tempListNode.next = null;
				return;
			}
			pre = tempListNode;
			tempListNode = tempListNode.next;
			position ++ ;
		}
		
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一个模块——主函数main()的功能是:根据选单的选项调用各函数,并完成相应的功能。 
   第二个模块——Menu()的功能是:显示提示选单。 
   第三个模块——Quit()的功能是:退出选单。 
   第四个模块——Create()的功能是:创建新的数据记录。 
   第五个模块——Add()的功能是:增加新的数据记录,并返回选单。 
   第六个模块——Find()的功能是:按要求查询相关的信息,如果找到了,则显示该信息,如果未找到,则提示文件中没有该信息,并返回选单。 
   第七个模块——Alter()[的功能是:修改某条记录的信息,如果未找到要修改的记录,则提示系统中无此记录,并返回选单。 
   第八个模块——Delete()的功能是:删除某条记录,如果未找到要删除的记录,则提示通讯录中没有,并返回选单。 
   第九个模块——List()的功能是:显示所有记录。 一、用链表或者顺序表实现以下系统,完成线性表的建立(至少包括10个结点),以及线性表中信息(结点)的插入、查找、删除、修改、输出等操作,具体的模块要求见上方的“总的模块要求”。建议用“文件”存储数据。 1.通讯录管理系统的设计与实现 (1)通讯者信息包括:编号(char num[10])、姓名(char name[10])、性别(char sex[10])、电话(char phone[20]) (2)除了总的模块要求外,还需统计通讯录中男性人数及女性人数,并求出通讯录中的第一个模块——主函数main()的功能是:根据选单的选项调用各函数,并完成相应的功能。 
   第二个模块——Menu()的功能是:显示提示选单。 
   第三个模块——Quit()的功能是:退出选单。 
   第四个模块——Create()的功能是:创建新的数据记录。 
   第五个模块——Add()的功能是:增加新的数据记录,并返回选单。 
   第六个模块——Find()的功能是:按要求查询相关的信息,如果找到了,则显示该信息,如果未找到,则提示文件中没有该信息,并返回选单。 
   第七个模块——Alter()[的功能是:修改某条记录的信息,如果未找到要修改的记录,则提示系统中无此记录,并返回选单。 
   第八个模块——Delete()的功能是:删除某条记录,如果未找到要删除的记录,则提示通讯录中没有,并返回选单。 
   第九个模块——List()的功能是:显示所有记录。 一、用链表或者顺序表实现以下系统,完成线性表的建立(至少包括10个结点),以及线性表中信息(结点)的插入、查找、删除、修改、输出等操作,具体的模块要求见上方的“总的模块要求”。建议用“文件”存储数据。 1.通讯录管理系统的设计与实现 (1)通讯者信息包括:编号(char num[10])、姓名(char name[10])、性别(char sex[10])、电话(char phone[20]) (2)除了总的模块要求外,还需统计通讯录中男性人数及女性人数,并求出通讯录中的男女比例。 男女比例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值