您的位置:首页 > 理论基础 > 数据结构算法

数据结构--链表

2013-10-22 16:29 134 查看
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
(顺序表)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: