数据结构--链表

1、概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。相比于线性表顺序结构,链表比较方便插入和删除操作。


链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必按顺序存储,链表在插入的时候可以达到O⑴的复杂度,比另一种线性表:顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间而顺序表(顺序表是在计算机内存中以数组的形式保存的线性表,采用顺序存储结构的线性表简称为“ 顺序表”)相应的时间复杂度分别是O(logn)和O⑴。链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。


链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。线性表的链式存储表示,有一个缺点就是要找一个数,必须要从头开始找起,十分麻烦。


(1)数组和链表的区别。(很简单,但是很常考,记得要回答全面)

答:C++语言中可以用数组处理一组数据类型相同的数据,但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小。而在实际应用中,用户使用数组之前有时无法准确确定数组的大小,只能将数组定义成足够大小,这样数组中有些空间可能不被使用,从而造成内存空间的浪费。链表是一种常见的数据组织形式,它采用动态分配内存的形式实现。需要时可以用new分配内存空间,不需要时用delete将已分配的空间释放,不会造成内存空间的浪费。


从逻辑结构来看:数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况,即数组的大小一旦定义就不能改变。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)。  


从内存存储来看:(静态)数组从栈中分配空间(用NEW创建的在堆中), 对于程序员方便快速,但是自由度小;链表从堆中分配空间, 自由度大但是申请管理比较麻烦.


从访问方式来看:数组在内存中是连续存储的,因此,可以利用下标索引进行随机访问;链表是链式存储结构,在访问元素的时候只能通过线性的方式由前到后顺序访问,所以访问效率比数组要低。


2、建立链表

Node节点:

private static class Node {
		int num;
		Node nextNode;

		public Node(int num) {
			this.num = num;
			nextNode = null;
		}

		public Node() {
			nextNode = null;
		}
	}
	
	static void printList(Node head) {
		Node temp = head.nextNode;
		while (temp != null) {
			System.out.println("node:" + temp.num);
			temp = temp.nextNode;
		}
	}

	static Node getNewList() {
		Node head = new Node();// head一般不存数据,方便删除操作等。
		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		Node node4 = new Node(4);

		head.nextNode = node1;
		node1.nextNode = node2;
		node2.nextNode = node3;
		node3.nextNode = node4;

		printList(head);
		return head;
	}

3、链表的插入、删除

插入

static void insertNode(Node head, Node data, int index) {// 将temp插入到第index个位置
		int i = 0;
		Node pre = head;
		Node temp = head.nextNode;
		while (temp != null) {
			i++;
			if (i == index) {
				pre.nextNode = data;
				data.nextNode = temp;
				break;
			}
			pre = temp;
			temp = temp.nextNode;
		}

		printList(head);
	}


删除

static void delete(Node head, int delNum) {// 删除num为delNum的节点
		Node pre = head;
		Node temp = head.nextNode;
		while (temp != null) {
			if (temp.num == delNum) {
				pre.nextNode = temp.nextNode;
				temp.nextNode = null;
				temp = pre.nextNode;
			} else {
				pre = temp;
				temp = temp.nextNode;
			}
		}

		printList(head);
	}

4、链表反转

static void reverse(Node head) {// 链表的反转
		if (head == null || head.nextNode == null) {
			return;
		}
		Node firstNode = head.nextNode;
		Node preNode = head.nextNode;
		Node curNode = head.nextNode.nextNode;
		Node nextNode;
		while (curNode != null) {
			nextNode = curNode.nextNode;
			curNode.nextNode = preNode;
			preNode = curNode;
			curNode = nextNode;
		}
		firstNode.nextNode = null;
		head.nextNode = preNode;

		printList(head);
	}


5、实验结果

public static void main(String[] args) {
		System.out.println("----------创建链表---------");
		Node head = getNewList();

		System.out.println("----------将data插入到第二个位置---------");
		Node data = new Node(-1);
		insertNode(head, data, 2);

		System.out.println("----------删除num为-1的节点-------");
		delete(head, -1);

		System.out.println("----------反转链表-------");
		reverse(head);
	}

结果如下图:




相关引用:

http://baike.baidu.com/link?url=a_O8HDsC8tCBSpA-QdULYAsSxS0XHLu62QVRfHixy_G8m-l8RMoZnOo353qwnpPo  (链表)

http://baike.baidu.com/link?url=7IhCZcwnZnE-uZOc5vE3hs6Gkc_45JUREtjWOuAQQA1Tieu_nOAmPmXK4FZVBTNv   (顺序表)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值