数据结构之链表单向操作总结

链表是数据结构的基础内容之一,下面就链表操作中的创建链表、打印链表、求取链表长度、判断链表是否为空、查找结点、插入结点、删除结点、逆转链表、连接链表、链表结点排序等进行总结。

1.创建表示结点的类,因为链表操作中需要比较结点,因此结点需要实现comparable接口。

public class Node implements Comparable<Node> {
	private Object data;
	private Node next;

	//构造函数
	public Node() {
		this.data = null;
		this.next = null;
	}
	//构造函数重载
	public Node(Object data) {
		this.data = data;
		this.next = null;
	}
	public Node(Object data, Node next) {
		this.data = data;
		this.next = next;
	}

	//读结点数据
	public Object getData() {
		return data;
	}
	//写结点数据
	public void setData(Object data) {
		this.data = data;
	}
	//获取结点链接的下一个点
	public Node getNext() {
		return next;
	}
	//设置结点链接的下一个点
	public void setNext(Node next) {
		this.next = next;
	}

	@Override
	public int compareTo(Node o) {
		if((Integer)this.data == (Integer)o.getData()) {
			return 0;
		}
		else {
			if((Integer)this.data < (Integer)o.getData()) {
				return -1;
			}
			else {
				return 1;
			}
		}
	}
}

2.链表类如下。

public class Link{
	/**
	 * 链表头结点
	 */
	private Node m_headNode = null;

	/**
	 * 链表长度
	 */
	private int m_length = 0;

	/**
	 * 获取链表头结点
	 *
	 * @return 链表头结点
	 */
	public Node getheadNode() {
		return m_headNode;
	}

	/**
	 * 获取链表长度
	 *
	 * @return 链表长度
	 */
	public int getLength() {
		return m_length;
	}

	/**
	 * 对以head为头结点的链表中的各个元素进行打印输出
	 *
	 * @param head 链表的头结点
	 */
	public void printLink() {
		Node p = m_headNode;
		while(p != null) {
			System.out.print(p.getData() + " ");
			p = p.getNext();
		}
		System.out.println();
	}

	/**
	 * 用来创建一个链表,data数组中的数据对应链表中各个结点的data值
	 *
	 * @param data 链表中各个结点的数据信息
	 * @return 链表的头结点
	 */
	public Node createLink(Object[] data) {
		Node headNode = null, r = null;
		for(int i=0; i<data.length; i++) {
			Node p = new Node();
			p.setData(data[i]);
			p.setNext(null);
			if(headNode == null) {
				headNode = p;
			}
			else {
				r.setNext(p);
			}
			r = p;
			this.m_length++;
		}
		this.m_headNode = headNode;
		return headNode;
	}

	/**
	 * 求线性链表的长度
	 *
	 * @return 链表的长度
	 */
	public int linkLength() {
		/*常规算法
		int n = 0;
		Node p = head;
		while(p != null) {
			n++;
			p = p.getNext();
		}
		return n;
		 */
		/*递归算法
		if(head != null) {
			return 1 + linkLength(head.getNext());
		} else {
			return 0;
		}
		*/
		return m_length;
	}

	/**
	 * 判断线性链表是否为空
	 *
	 * @param headNode 链表的头结点
	 * @return 若链表为空,返回true;否则返回false
	 */
	public boolean isEmpty() {
		return m_headNode == null;
	}

	/**
	 * 查找链表中item的地址
	 *
	 * @param item 查找的目标结点的地址
	 * @return 如果结点存在,返回结点;否则返回空
	 */
	public Node findElement(Object item) {
		Node p = m_headNode;
		while(p != null) {
			if(p.getData() == item) {
				return p;
			}
			p = p.getNext();
		}
		return null;
	}

	/**
	 * 在链表头结点之前插入结点,使之成为头结点
	 *
	 * @param data 插入的结点数据
	 */
	public void insertHeadNode(Object data) {
		Node node = new Node(data, null);
		node.setNext(m_headNode);
		m_headNode = node;
		m_length++;
	}

	/**
	 * 在链表尾部插入结点,使之成为尾结点
	 *
	 * @param data 插入的结点数据
	 */
	public void insertTailNode(Object data) {
		Node p = m_headNode;
		while(p.getNext() != null) {
			p = p.getNext();
		}
		Node node = new Node(data, null);
		p.setNext(node);
		m_length++;
	}

	/**
	 * 在链表的第pos个位置后插入数据为data的结点
	 *
	 * @param pos 插入结点的位置
	 * @param data 插入结点的数据
	 * @return 正确插入返回1;否则返回0
	 */
	public int insertNode(int pos, Object data) {
		if(pos <= 0 || pos > m_length) {
			return 0;
		}
		int n = 0;
		Node p = m_headNode;
		while(p != null) {
			n++;
			if(n == pos) {
				Node node = new Node(data);
				node.setNext(p.getNext());
				p.setNext(node);
				m_length++;
				return 1;
			}
			p = p.getNext();
		}
		return 0;
	}

	/**
	 * 删除链表中第一次出现数据为data的结点
	 *
	 * @param data 被删除的结点数据
	 * @return 链表中存在该结点且删除成功,返回true;否则,返回false
	 */
	public boolean deleteNode(Object data) {
		if(m_headNode.getData() == data) {
			m_headNode = m_headNode.getNext();
			m_length--;
			return true;
		}
		Node p = m_headNode, r = null;
		while(p != null) {
			if(p.getData() == data) {
				r.setNext(p.getNext());
				m_length--;
				return true;
			}
			else {
				r = p;
				p = p.getNext();
			}
		}
		return false;
	}

	/**
	 * 删除链表中数据元素为data的所有结点
	 *
	 * @param data 链表中被删结点的数据
	 */
	public void deleteAllNode(Object data) {
		Node p = m_headNode.getNext(), r = m_headNode;
		while(p != null) {
			if(p.getData() == data) {
				r.setNext(p.getNext());
				p = p.getNext();
				m_length--;
			}
			else {
				r = p;
				p = p.getNext();
			}
		}
		if(m_headNode.getData() == data) {
			m_headNode = m_headNode.getNext();
			m_length--;
		}
	}

	/**
	 * 逆转链表
	 */
	public void invertLink() {
		Node p = m_headNode, r, q = null;
		while(p != null) {
			r = q;
			q = p;
			p = p.getNext();
			q.setNext(r);
		}
		m_headNode = q;
	}

	/**
	 * 将该链表链接在headLink之后
	 *
	 * @param link 被链接的链表
	 * @throws NullPointerException 如果被链接的链表中一个结点都没有,抛出空指针异常
	 */
	public void connectFrom(Link link) throws NullPointerException {
		if(link.getheadNode() == null) {
			throw new NullPointerException();
		}
		else {
			Node p = link.getheadNode(), r = null;
			while(p != null) {
				r = p;
				p = p.getNext();
			}
			r.setNext(m_headNode);
			m_headNode = link.getheadNode();
			m_length += link.getLength();
		}
	}

	/**
	 * 在链表尾部追加link链表
	 *
	 * @param link 需要追加的链表
	 */
	public void connectTo(Link link) {
		Node p = m_headNode, r = null;
		while(p != null) {
			r = p;
			p = p.getNext();
		}
		r.setNext(link.getheadNode());
		m_length += link.getLength();
	}

	/**
	 * 对链表各结点数据从小到大排序
	 *
	 * @throws NullPointerException 如果链表中一个结点都没有,则抛出空指针异常
	 */
	public void sort() throws NullPointerException {
		if(m_headNode == null) {
			throw new NullPointerException();
		}
		else {
			Node r = m_headNode, p = m_headNode.getNext(), q = null;
			int count = 1;
			while(p != null) {
				if(p.compareTo(r) == -1) {
					q = p;
					r.setNext(p.getNext());
					p = p.getNext();
					insert(q, count);
				}
				else {
					r = p;
					p = p.getNext();
				}
				count++;
			}
		}
	}

	/**
	 * 将结点p插入一个顺序排列的长度为length的链表中,使得插入结点p后的链表仍然顺序排列
	 *
	 * @param p 需要插入的结点
	 * @param length 顺序排列的链表的长度
	 */
	private void insert(Node p, int length) {
		if(p.compareTo(m_headNode) == -1) {
			p.setNext(m_headNode);
			m_headNode = p;
		}
		else {
			Node r = m_headNode.getNext(), q = m_headNode;
			for(int i = 2; i < length; i++) {
				if(p.compareTo(r) == 1) {
					q = r;
					r = r.getNext();
				}
				else {
					q.setNext(p);
					p.setNext(r);
					return;
				}
			}
			q.setNext(p);
			p.setNext(r);
		}
	}
}

数据结构之链表单向操作总结,布布扣,bubuko.com

时间: 2024-10-09 18:17:29

数据结构之链表单向操作总结的相关文章

数据结构——单链表及其操作

1 #include<iostream> 2 #include<string> 3 #include<stdlib.h> 4 5 using namespace std; 6 7 typedef int ElemType; 8 typedef int Status; 9 #define OK 1 10 #define ERROR 0 11 12 13 //单链表的存储结构 14 typedef struct LNode 15 { 16 ElemType data; //

文章分享:简单数据结构学习:单向链表

文章分享:简单数据结构学习:单向链表:https://www.textarea.com/aprikyb/jiandan-shujujiegou-xuexi-danxiang-lianbiao-252/

java数据结构:单链表常见操作代码实现

一.概述: 本文主要总结单链表常见操作的实现,包括链表结点添加.删除:链表正向遍历和反向遍历.链表排序.判断链表是否有环.是否相交.获取某一结点等. 二.概念: 链表: 一种重要的数据结构,HashMap等集合的底层结构都是链表结构.链表以结点作为存储单元,这些存储单元可以是不连续的.每个结点由两部分组成:存储的数值+前序结点和后序结点的指针.即有前序结点的指针又有后序结点的指针的链表称为双向链表,只包含后续指针的链表为单链表,本文总结的均为单链表的操作. 单链表结构: Java中单链表采用No

数据结构之链表操作

#include <IOSTREAM> #include <IOMANIP> #include <STRING> using namespace std; typedef struct Student { int id; char name[20]; char sex[20]; struct Student *next; }node; typedef node * pnode; pnode Create(); void Print(pnode h); void Sort

Java数据结构之链表的原理及LinkedList的部分源码剖析

一.为什么要学习数据结构? 做为一名程序员,不管你是用什么编程语言,数据结构是取底层的东西.就相当于盖楼的地基一样,地基做不好,上边再好也没有用. 在高级语言中,一般会对这些基础的数据结构进行封装,我们学要学习这些基础的东西吗? 当然是的,只有知道这些基础的东西,我们才能更好地使用语言封装好的api.举个最简单的例子,在Java中,List的实现类有ArrayList,LinkedList,Vector,你知道在什么情况下用哪个效率最高吗?只有知道其底层源才能更好地利用. 如何学习数据结构? 可

基本数据结构:链表(list)

copy from:http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html 基本数据结构:链表(list) 谈到链表之前,先说一下线性表.线性表是最基本.最简单.也是最常用的一种数据结构.线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的.线性表有两种存储方式,一种是顺序存储结构,另一种是链式存储结构. 顺序存储结构就是两个相邻的元素在内存中也是相邻的.这种存储方式的优点是

数据结构之——链表(list)、队列(queue)和栈(stack)

在前面几篇博文中曾经提到链表(list).队列(queue)和(stack),为了更加系统化,这里统一介绍着三种数据结构及相应实现. 1)链表 首先回想一下基本的数据类型,当需要存储多个相同类型的数据时,优先使用数组.数组可以通过下标直接访问(即随机访问),正是由于这个优点,数组无法动态添加或删除其中的元素,而链表弥补了这种缺陷.首先看一下C风格的单链表节点声明: 1 typedef struct _ListNode{ 2 int val; 3 struct _ListNode *next; 4

数据结构:链表的基本操作(创建,删除,插入,逆序,摧毁)

代码注释比较详细: #include <iostream> #include <cstdlib> using namespace std; struct Node{ int data; Node* next; }; Node* head = NULL; bool create() { head = (Node*)malloc(sizeof(Node)); if(NULL == head) return false; head->data = 0; head->next

最基础的动态数据结构:链表

什么是链表 链表是一种线性结构,也是最基础的动态数据结构.我们在实现动态数组.栈以及队列时,底层都是依托的静态数组,靠resize来解决固定容量的问题,而链表是真正的动态数据结构.学习链表这种数据结构,能够更深入的理解引用(或者指针)以及递归.其中链表分为单链链表和双链链表,本文中所介绍的是单链链表. 链表中的数据是存储在一个个的节点中,如下这是一个最基本的节点结构: class Node { E e; Node next; // 节点中持有下一个节点的引用 } 我们可以将链表想象成火车,每一节