大话数据结构二:线性表的链式存储结构(单链表)

1. 线性表的链式存储结构:指的是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的,这就意味着这些数据元素可以存在内存未被占用的任意位置。


2. 结点:结点由存放数据元素的数据域和存放后继结点地址的指针域组成。

1.)顺序存储结构中,每个数据元素只需要存数据元素的信息就可以了。

2.)链式存储结构中,除了要存储数据元素信息外,还要存储它的后继元素的存储地址。

3.)链表中第一个结点叫头结点,它的存储位置叫做头指针,它的数据域可以不存储任何信息,链表的最后一个结点指针为空。


3. Java实现单链表:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // 单向链表  
  2. public class SingleLinkedList<E> {  
  3.     private Node<E> head; // 头结点  
  4.     private int size; // 链表长度  
  5.   
  6.     // 建立一个空链表  
  7.     public SingleLinkedList() {  
  8.         head = null;  
  9.         size = 0;  
  10.     }  
  11.       
  12.     // 在链表尾部插入  
  13.     public boolean add(E data){  
  14.         Node<E> newNode = new Node<E>(data);  
  15.         if(isEmpty()){  
  16.             head = newNode;  
  17.         }else{  
  18.             Node<E> tail = get(size);  
  19.             tail.setNext(newNode);  
  20.         }  
  21.         size++;  
  22.         return true;  
  23.     }  
  24.   
  25.     // 插入指定位置的结点  
  26.     public boolean insert(int position, E data) {  
  27.         if(position >= 1 && (position <= size + 1)){  
  28.             Node<E> newNode = new Node<E>(data);  
  29.             if(isEmpty() || position == 1){ // 链表为空或在头结点前插入  
  30.                 newNode.setNext(head);  
  31.                 head = newNode;  
  32.             }else// 在中间位置插入  
  33.                 Node<E> preNode = get(position - 1); // 获取position的前一结点  
  34.                 Node<E> originalNode = preNode.getNext(); // 获取未插入结点时position位置对应结点   
  35.                 preNode.setNext(newNode);  
  36.                 newNode.setNext(originalNode);  
  37.             }  
  38.             size++;  
  39.             return true;  
  40.         }  
  41.         return false;  
  42.     }  
  43.   
  44.     // 删除指定位置的结点  
  45.     public E delete(int position) {   
  46.         E result = null;  
  47.         if(position >= 1 && position <= size){  
  48.             if(position == 1){ // 删除头结点  
  49.                 result = head.getData();  
  50.                 Node<E> afterHead = head.getNext();  
  51.                 head = afterHead;  
  52.             }else// 删除其他结点  
  53.                 Node<E> preNode = get(position - 1); // 获取待删除结点的前一结点  
  54.                 Node<E> curNode = preNode.getNext(); // 获取待删除结点  
  55.                 result = curNode.getData();  
  56.                 preNode.setNext(curNode.getNext()); // 将待删除结点前一结点指向待删除结点下一结点  
  57.             }  
  58.             size--;  
  59.         }  
  60.         return result;  
  61.     }  
  62.       
  63.     // 获取某个位置的结点  
  64.     public Node<E> get(int position){  
  65.         Node<E> targetNode = null;  
  66.         if(!isEmpty() && position >= 1 && position <= size){   
  67.             targetNode = head;  
  68.             for(int i = 1; i < position ; i++){  
  69.                 targetNode = targetNode.getNext(); // 循环获取对应位置的结点  
  70.             }  
  71.         }  
  72.         return targetNode;  
  73.     }  
  74.       
  75.     // 获取链表的长度  
  76.     public int getSize(){  
  77.         return size;  
  78.     }  
  79.       
  80.     // 判断链表是否为空  
  81.     public boolean isEmpty(){  
  82.         return size == 0;  
  83.     }  
  84.       
  85.     // 打印链表数据  
  86.     public void display(){  
  87.         Node<E> node = head;  
  88.         System.out.print("单链表: ");  
  89.         for(int i = 0; i < size; i++){  
  90.             System.out.print(" " + node.getData());  
  91.             node = node.getNext();  
  92.         }  
  93.         System.out.println("");  
  94.     }  
  95. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // 结点类,包含结点的数据和指向下一个节点的引用  
  2. public class Node<E> {  
  3.     private E data;  // 数据域  
  4.     private Node<E> next;  // 指针域保存着下一节点的引用  
  5.   
  6.     public Node() {  
  7.     }  
  8.   
  9.     public Node(E data) {  
  10.         this.data = data;  
  11.     }  
  12.       
  13.     public Node(E data,Node<E> next) {  
  14.         this.data = data;  
  15.         this.next = next;  
  16.     }  
  17.   
  18.     public void setNext(Node<E> next) {  
  19.         this.next = next;  
  20.     }  
  21.   
  22.     public Node<E> getNext() {  
  23.         return next;  
  24.     }  
  25.   
  26.     public E getData() {  
  27.         return data;  
  28.     }  
  29.   
  30.     public void setData(E data) {  
  31.         this.data = data;  
  32.     }  
  33.   
  34.     @Override  
  35.     public String toString() {  
  36.         return "" + data;  
  37.     }  
  38. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // 测试类  
  2. public class Main {  
  3.     public static void main(String[] args) {  
  4.         SingleLinkedList<Integer> circular = new SingleLinkedList<Integer>();  
  5.         circular.add(1);  
  6.         circular.add(2);  
  7.         circular.add(3);  
  8.         circular.insert(4,4);  
  9.         circular.insert(5,5);  
  10.         circular.insert(6,6);  
  11.         circular.delete(3);  
  12.         circular.delete(5);  
  13.         circular.display();  
  14.         System.out.println("链表的长度为:  " + circular.getSize());  
  15.     }  
  16. }  
4. 单链表结构和顺序存储结构优缺点:

1.)若线性表需要频繁查找,很少进行插入和删除操作,宜采用顺序存储结构,若需要频繁插入和删除时,宜采用单链表结构。

2.)当线性表的元素个数变化较大或者根本就不知道多大时,最好用单链表结构,这样可以不需要考虑存储空间的大小问题。单链表所占大小和位置是不需要预先分配划定的,可以根据系统的情况和实际的需求即时生成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值