浅谈数据结构之线性表(一)

本文介绍了线性表的基本概念,包括其特点和数据元素关系。接着对比了数组和链表的优缺点,指出数组在随机访问和查找速度上的优势,以及链表在插入删除效率和内存利用上的灵活性。文章还详细讨论了单链表、双链表和循环链表,特别是循环链表的实现和操作,如头尾插入、删除等。
摘要由CSDN通过智能技术生成

基本概念

线性表是一种逻辑结构,相同数据类型的n个数据元素的有限序列,除第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外,每个元素有且仅有一个直接后继。
线性表具有以下特点:

  • 元素个数有限
  • 逻辑上元素有先后次序
  • 数据类型相同
  • 仅讨论元素间的逻辑关系
    在这里插入图片描述

数组和链表

数组的优点
  • 随机访问性强
  • 查找速度快
数组的缺点
  • 插入和删除效率低
  • 可能浪费内存
  • 内存要求高,必须有连续的内存空间
  • 数组大小固定,不能动态扩展
链表的优点
  • 插入删除速度快
  • 内存利用率高,不会浪费内存
  • 大小内有固定,拓展很灵活
链表的缺点
  • 不能随机查找,必须从第一个开始遍历,查找效率低
操作效率
操作数组链表
读取O(1)O(N)
插入O(n)O(1)
删除O(n)O(1)

单链表、双链表、循环链表

单链表

在这里插入图片描述

双链表

在这里插入图片描述

循环链表
  1. 循环单链表
    与单链表的区别在于,表中最后一个节点的指针不为null,而改为指向头结点(第一个节点),从而整个链表形成一个环。判断循环单链表是否为空,判断是否等于头指针。只有一个尾指针的循环单链表,可以很方便的操作表头和表尾,因为尾指针的后继就是头指针O(1) 。
  2. 循环双链表
    与双链表的区别在于,头结点的prior指针指向尾节点,尾节点的next指针指向头结点。

基本操作

  1. 头节点插入
    在这里插入图片描述
  2. 尾节点插入
    在这里插入图片描述
  3. 插入
    在这里插入图片描述
  4. 删除
    在这里插入图片描述

基本操作实战

数据结构存储类 ListNode.java
public class ListNode {

	public int value;
	
	public ListNode next;
	
	public ListNode(int value) {
		this.value = value;
	}
}
操作方法类 MyList.java
public class MyList {
	
	
	/**
	 * 头节点插入
	 * @param head
	 * @param newNode
	 */
	public static void headInsert(ListNode head, ListNode newNode) {
		newNode.next = head;
	}
	
	/**
	 * 尾节点插入
	 * @param tail
	 * @param newNode
	 */
    public static void tailInsert(ListNode tail, ListNode newNode) {
		tail.next = newNode;
	}
	
    /**
     * 遍历
     * @param head
     */
    public static void traverse(ListNode head) {
    	while (head != null) {
			System.out.print(head.value + " ");	
			head = head.next;
		}
    }
    
    /**
     * 查找
     * @param head
     * @param value
     * @return
     */
    public static int find(ListNode head, int value) {
    	int index = -1;
    	int count = 0;
    	while (head != null) {
			if (value == head.value) {
				index = count;
				break;
			}	
			head = head.next;
			count ++;
		}
    	return index;
    }
    
	/**
	 * 插入
	 * @param p
	 * @param s
	 */
	public static void insert(ListNode p, ListNode s) {
		ListNode next = p.next;
		p.next = s;
		s.next = next;
	}
	
	/**
	 * 删除
	 * @param head
	 * @param q
	 */
	public static void delete(ListNode head, ListNode q) {
		if (q.next != null) {
			ListNode next = q.next;
			q.value = next.value;
			q.next = next.next;
			next = null;
		} else {
			while (head != null) {
				if (head.next == q) {
					head.next = null;
					q = null;
					break;
				}
				head = head.next;
			}
		}
	}
	
    public static void main(String[] args) {
		ListNode node1 = new ListNode(1);
		ListNode node2 = new ListNode(2);
		ListNode node3 = new ListNode(3);
		ListNode node4 = new ListNode(4);
		node1.next = node2;
		node2.next = node3;
		node3.next = node4;
		//头节点插入
		ListNode node0 = new ListNode(0);
		headInsert(node1, node0);
		System.out.print("头节点插入 :");
		traverse(node0);
		System.out.println();
		//尾节点插入
		ListNode node5 = new ListNode(5);
		tailInsert(node4, node5);
		System.out.print("尾节点插入 :");
		traverse(node0);
		System.out.println();
		//遍历
		System.out.print("遍历 :");
		traverse(node0);
		System.out.println();
		//查找
		int index = find(node0, 4);
		System.out.print("查找结果位置:" + index);
		//插入
		ListNode node6 = new ListNode(6);
		insert(node2, node6);
		System.out.println();
		//遍历
		System.out.print("插入之后遍历 :");
		traverse(node0);
		//删除
		delete(node0, node6);
		System.out.println();
		System.out.print("删除之后遍历 :");
		traverse(node0);
		//删除
		delete(node0, node3);
		System.out.println();
		System.out.print("删除之后遍历 :");
		traverse(node0);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值