• 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现


     

    概要

    线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列。本章先介绍线性表的几个基本组成部分:数组、单向链表、双向链表;随后给出双向链表的C、C++和Java三种语言的实现。内容包括:
    数组
    单向链表
    双向链表
          1. C实现双链表
          2. C++实现双链表
          3. Java实现双链表

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3561803.html


    更多内容

    数据结构与算法系列 目录

    数组

    数组有上界和下界,数组的元素在上下界内是连续的。

    存储10,20,30,40,50的数组的示意图如下:


    数组的特点是:数据是连续的;随机访问速度快。
    数组中稍微复杂一点的是多维数组和动态数组。对于C语言而言,多维数组本质上也是通过一维数组实现的。至于动态数组,是指数组的容量能动态增长的数组;对于C语言而言,若要提供动态数组,需要手动实现;而对于C++而言,STL提供了Vector;对于Java而言,Collection集合中提供了ArrayList和Vector。

     

    单向链表

    单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针。

    单链表的示意图如下:

    表头为空,表头的后继节点是"节点10"(数据为10的节点),"节点10"的后继节点是"节点20"(数据为10的节点),...

    单链表删除节点

    删除"节点30"
    删除之前:"节点20" 的后继节点为"节点30",而"节点30" 的后继节点为"节点40"。
    删除之后:"节点20" 的后继节点为"节点40"。

    单链表添加节点

    在"节点10"与"节点20"之间添加"节点15"
    添加之前:"节点10" 的后继节点为"节点20"。
    添加之后:"节点10" 的后继节点为"节点15",而"节点15" 的后继节点为"节点20"。

    单链表的特点是:节点的链接方向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很高。

     

    双向链表

    双向链表(双链表)是链表的一种。和单链表一样,双链表也是由节点组成,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

    双链表的示意图如下:

    表头为空,表头的后继节点为"节点10"(数据为10的节点);"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前继节点是"节点10";"节点20"的后继节点是"节点30","节点30"的前继节点是"节点20";...;末尾节点的后继节点是表头。

    双链表删除节点

    删除"节点30"
    删除之前:"节点20"的后继节点为"节点30","节点30" 的前继节点为"节点20"。"节点30"的后继节点为"节点40","节点40" 的前继节点为"节点30"。
    删除之后:"节点20"的后继节点为"节点40","节点40" 的前继节点为"节点20"。

    双链表添加节点

    在"节点10"与"节点20"之间添加"节点15"
    添加之前:"节点10"的后继节点为"节点20","节点20" 的前继节点为"节点10"。
    添加之后:"节点10"的后继节点为"节点15","节点15" 的前继节点为"节点10"。"节点15"的后继节点为"节点20","节点20" 的前继节点为"节点15"。

    下面介绍双链表的实现,分别介绍C/C++/Java三种实现。

    1. C实现双链表

    实现代码
    双向链表头文件(double_link.h)

     1 #ifndef _DOUBLE_LINK_H
     2 #define _DOUBLE_LINK_H
     3 
     4 // 新建“双向链表”。成功,返回表头;否则,返回NULL
     5 extern int create_dlink();
     6 // 撤销“双向链表”。成功,返回0;否则,返回-1
     7 extern int destroy_dlink();
     8 
     9 // “双向链表是否为空”。为空的话返回1;否则,返回0。
    10 extern int dlink_is_empty();
    11 // 返回“双向链表的大小”
    12 extern int dlink_size();
    13 
    14 // 获取“双向链表中第index位置的元素”。成功,返回节点指针;否则,返回NULL。
    15 extern void* dlink_get(int index);
    16 // 获取“双向链表中第1个元素”。成功,返回节点指针;否则,返回NULL。
    17 extern void* dlink_get_first();
    18 // 获取“双向链表中最后1个元素”。成功,返回节点指针;否则,返回NULL。
    19 extern void* dlink_get_last();
    20 
    21 // 将“value”插入到index位置。成功,返回0;否则,返回-1。
    22 extern int dlink_insert(int index, void *pval);
    23 // 将“value”插入到表头位置。成功,返回0;否则,返回-1。
    24 extern int dlink_insert_first(void *pval);
    25 // 将“value”插入到末尾位置。成功,返回0;否则,返回-1。
    26 extern int dlink_append_last(void *pval);
    27 
    28 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1
    29 extern int dlink_delete(int index);
    30 // 删除第一个节点。成功,返回0;否则,返回-1
    31 extern int dlink_delete_first();
    32 // 删除组后一个节点。成功,返回0;否则,返回-1
    33 extern int dlink_delete_last();
    34 
    35 #endif 
    View Code

    双向链表实现文件(double_link.c)

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 
      4 /**
      5  * C 语言实现的双向链表,能存储任意数据。
      6  *
      7  * @author skywang
      8  * @date 2013/11/07
      9  */
     10 // 双向链表节点
     11 typedef struct tag_node 
     12 {
     13     struct tag_node *prev;
     14     struct tag_node *next;
     15     void* p;
     16 }node;
     17 
     18 // 表头。注意,表头不存放元素值!!!
     19 static node *phead=NULL;
     20 // 节点个数。
     21 static int  count=0;
     22 
     23 // 新建“节点”。成功,返回节点指针;否则,返回NULL。
     24 static node* create_node(void *pval)
     25 {
     26     node *pnode=NULL;
     27     pnode = (node *)malloc(sizeof(node));
     28     if (!pnode)
     29     {
     30         printf("create node error!
    ");
     31         return NULL;
     32     }
     33     // 默认的,pnode的前一节点和后一节点都指向它自身
     34     pnode->prev = pnode->next = pnode;
     35     // 节点的值为pval
     36     pnode->p = pval;
     37 
     38     return pnode;
     39 }
     40 
     41 // 新建“双向链表”。成功,返回0;否则,返回-1。
     42 int create_dlink()
     43 {
     44     // 创建表头
     45     phead = create_node(NULL);
     46     if (!phead)
     47         return -1;
     48 
     49     // 设置“节点个数”为0
     50     count = 0;
     51 
     52     return 0;
     53 }
     54 
     55 // “双向链表是否为空”
     56 int dlink_is_empty()
     57 {
     58     return count == 0;
     59 }
     60 
     61 // 返回“双向链表的大小”
     62 int dlink_size() {
     63     return count;
     64 }
     65 
     66 // 获取“双向链表中第index位置的节点”
     67 static node* get_node(int index) 
     68 {
     69     if (index<0 || index>=count)
     70     {
     71         printf("%s failed! index out of bound!
    ", __func__);
     72         return NULL;
     73     }
     74 
     75     // 正向查找
     76     if (index <= (count/2))
     77     {
     78         int i=0;
     79         node *pnode=phead->next;
     80         while ((i++) < index) 
     81             pnode = pnode->next;
     82 
     83         return pnode;
     84     }
     85 
     86     // 反向查找
     87     int j=0;
     88     int rindex = count - index - 1;
     89     node *rnode=phead->prev;
     90     while ((j++) < rindex) 
     91         rnode = rnode->prev;
     92 
     93     return rnode;
     94 }
     95 
     96 // 获取“第一个节点”
     97 static node* get_first_node() 
     98 {
     99     return get_node(0);
    100 }
    101 
    102 // 获取“最后一个节点”
    103 static node* get_last_node() 
    104 {
    105     return get_node(count-1);
    106 }
    107 
    108 // 获取“双向链表中第index位置的元素”。成功,返回节点值;否则,返回-1。
    109 void* dlink_get(int index)
    110 {
    111     node *pindex=get_node(index);
    112     if (!pindex) 
    113     {
    114         printf("%s failed!
    ", __func__);
    115         return NULL;
    116     }
    117 
    118     return pindex->p;
    119 
    120 }
    121 
    122 // 获取“双向链表中第1个元素的值”
    123 void* dlink_get_first()
    124 {
    125     return dlink_get(0);
    126 }
    127 
    128 // 获取“双向链表中最后1个元素的值”
    129 void* dlink_get_last()
    130 {
    131     return dlink_get(count-1);
    132 }
    133 
    134 // 将“pval”插入到index位置。成功,返回0;否则,返回-1。
    135 int dlink_insert(int index, void* pval) 
    136 {
    137     // 插入表头
    138     if (index==0)
    139         return dlink_insert_first(pval);
    140 
    141     // 获取要插入的位置对应的节点
    142     node *pindex=get_node(index);
    143     if (!pindex) 
    144         return -1;
    145 
    146     // 创建“节点”
    147     node *pnode=create_node(pval);
    148     if (!pnode)
    149         return -1;
    150 
    151     pnode->prev = pindex->prev;
    152     pnode->next = pindex;
    153     pindex->prev->next = pnode;
    154     pindex->prev = pnode;
    155     // 节点个数+1
    156     count++;
    157 
    158     return 0;
    159 }
    160 
    161 // 将“pval”插入到表头位置
    162 int dlink_insert_first(void *pval) 
    163 {
    164     node *pnode=create_node(pval);
    165     if (!pnode)
    166         return -1;
    167 
    168     pnode->prev = phead;
    169     pnode->next = phead->next;
    170     phead->next->prev = pnode;
    171     phead->next = pnode;
    172     count++;
    173     return 0;
    174 }
    175 
    176 // 将“pval”插入到末尾位置
    177 int dlink_append_last(void *pval) 
    178 {
    179     node *pnode=create_node(pval);
    180     if (!pnode)
    181         return -1;
    182     
    183     pnode->next = phead;
    184     pnode->prev = phead->prev;
    185     phead->prev->next = pnode;
    186     phead->prev = pnode;
    187     count++;
    188     return 0;
    189 }
    190 
    191 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。
    192 int dlink_delete(int index)
    193 {
    194     node *pindex=get_node(index);
    195     if (!pindex) 
    196     {
    197         printf("%s failed! the index in out of bound!
    ", __func__);
    198         return -1;
    199     }
    200 
    201     pindex->next->prev = pindex->prev;
    202     pindex->prev->next = pindex->next;
    203     free(pindex);
    204     count--;
    205 
    206     return 0;
    207 }    
    208 
    209 // 删除第一个节点
    210 int dlink_delete_first() 
    211 {
    212     return dlink_delete(0);
    213 }
    214 
    215 // 删除组后一个节点
    216 int dlink_delete_last() 
    217 {
    218     return dlink_delete(count-1);
    219 }
    220 
    221 // 撤销“双向链表”。成功,返回0;否则,返回-1。
    222 int destroy_dlink()
    223 {
    224     if (!phead)
    225     {
    226         printf("%s failed! dlink is null!
    ", __func__);
    227         return -1;
    228     }
    229 
    230     node *pnode=phead->next;
    231     node *ptmp=NULL;
    232     while(pnode != phead)
    233     {
    234         ptmp = pnode;
    235         pnode = pnode->next;
    236         free(ptmp);
    237     }
    238 
    239     free(phead);
    240     phead = NULL;
    241     count = 0;
    242 
    243     return 0;
    244 }
    View Code

    双向链表测试程序(dlink_test.c)

      1 #include <stdio.h>
      2 #include "double_link.h"
      3 
      4 /**
      5  * C 语言实现的双向链表的测试程序。
      6  *
      7  * (01) int_test()
      8  *      演示向双向链表操作“int数据”。
      9  * (02) string_test()
     10  *      演示向双向链表操作“字符串数据”。
     11  * (03) object_test()
     12  *      演示向双向链表操作“对象”。
     13  *
     14  * @author skywang
     15  * @date 2013/11/07
     16  */
     17 
     18 // 双向链表操作int数据
     19 void int_test()
     20 {
     21     int iarr[4] = {10, 20, 30, 40};
     22 
     23     printf("
    ----%s----
    ", __func__);
     24     create_dlink();        // 创建双向链表
     25 
     26     dlink_insert(0, &iarr[0]);    // 向双向链表的表头插入数据
     27     dlink_insert(0, &iarr[1]);    // 向双向链表的表头插入数据
     28     dlink_insert(0, &iarr[2]);    // 向双向链表的表头插入数据
     29 
     30     printf("dlink_is_empty()=%d
    ", dlink_is_empty());    // 双向链表是否为空
     31     printf("dlink_size()=%d
    ", dlink_size());            // 双向链表的大小
     32 
     33     // 打印双向链表中的全部数据
     34     int i;
     35     int *p;
     36     int sz = dlink_size();
     37     for (i=0; i<sz; i++)
     38     {
     39         p = (int *)dlink_get(i);
     40         printf("dlink_get(%d)=%d
    ", i, *p);
     41     }
     42 
     43     destroy_dlink();
     44 }
     45 
     46 void string_test()
     47 {
     48     char* sarr[4] = {"ten", "twenty", "thirty", "forty"};
     49 
     50     printf("
    ----%s----
    ", __func__);
     51     create_dlink();        // 创建双向链表
     52 
     53     dlink_insert(0, sarr[0]);    // 向双向链表的表头插入数据
     54     dlink_insert(0, sarr[1]);    // 向双向链表的表头插入数据
     55     dlink_insert(0, sarr[2]);    // 向双向链表的表头插入数据
     56 
     57     printf("dlink_is_empty()=%d
    ", dlink_is_empty());    // 双向链表是否为空
     58     printf("dlink_size()=%d
    ", dlink_size());            // 双向链表的大小
     59 
     60     // 打印双向链表中的全部数据
     61     int i;
     62     char *p;
     63     int sz = dlink_size();
     64     for (i=0; i<sz; i++)
     65     {
     66         p = (char *)dlink_get(i);
     67         printf("dlink_get(%d)=%s
    ", i, p);
     68     }
     69 
     70     destroy_dlink();
     71 }
     72 
     73 typedef struct tag_stu
     74 {
     75     int id;
     76     char name[20];
     77 }stu;
     78 
     79 static stu arr_stu[] = 
     80 {
     81     {10, "sky"},
     82     {20, "jody"},
     83     {30, "vic"},
     84     {40, "dan"},
     85 };
     86 #define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) )
     87 
     88 void object_test()
     89 {
     90     printf("
    ----%s----
    ", __func__);
     91     create_dlink();    // 创建双向链表
     92 
     93     dlink_insert(0, &arr_stu[0]);    // 向双向链表的表头插入数据
     94     dlink_insert(0, &arr_stu[1]);    // 向双向链表的表头插入数据
     95     dlink_insert(0, &arr_stu[2]);    // 向双向链表的表头插入数据
     96 
     97     printf("dlink_is_empty()=%d
    ", dlink_is_empty());    // 双向链表是否为空
     98     printf("dlink_size()=%d
    ", dlink_size());            // 双向链表的大小
     99 
    100     // 打印双向链表中的全部数据
    101     int i;
    102     int sz = dlink_size();
    103     stu *p;
    104     for (i=0; i<sz; i++)
    105     {
    106         p = (stu *)dlink_get(i);
    107         printf("dlink_get(%d)=[%d, %s]
    ", i, p->id, p->name);
    108     }
    109 
    110     destroy_dlink();
    111 }
    112 
    113 int main()
    114 {
    115     int_test();        // 演示向双向链表操作“int数据”。
    116     string_test();    // 演示向双向链表操作“字符串数据”。
    117     object_test();    // 演示向双向链表操作“对象”。
    118 
    119     return 0;
    120 }
    View Code

    运行结果

    ----int_test----
    dlink_is_empty()=0
    dlink_size()=3
    dlink_get(0)=30
    dlink_get(1)=20
    dlink_get(2)=10
    
    ----string_test----
    dlink_is_empty()=0
    dlink_size()=3
    dlink_get(0)=thirty
    dlink_get(1)=twenty
    dlink_get(2)=ten
    
    ----object_test----
    dlink_is_empty()=0
    dlink_size()=3
    dlink_get(0)=[30, vic]
    dlink_get(1)=[20, jody]
    dlink_get(2)=[10, sky]

    2. C++实现双链表

    实现代码
    双向链表文件(DoubleLink.h)

      1 #ifndef DOUBLE_LINK_HXX
      2 #define DOUBLE_LINK_HXX
      3 
      4 #include <iostream>
      5 using namespace std;
      6 
      7 template<class T> 
      8 struct DNode 
      9 {
     10     public:
     11         T value;
     12         DNode *prev;
     13         DNode *next;
     14     public:
     15         DNode() { }
     16         DNode(T t, DNode *prev, DNode *next) {
     17             this->value = t;
     18             this->prev  = prev;
     19             this->next  = next;
     20            }
     21 };
     22 
     23 template<class T> 
     24 class DoubleLink 
     25 {
     26     public:
     27         DoubleLink();
     28         ~DoubleLink();
     29 
     30         int size();
     31         int is_empty();
     32 
     33         T get(int index);
     34         T get_first();
     35         T get_last();
     36 
     37         int insert(int index, T t);
     38         int insert_first(T t);
     39         int append_last(T t);
     40 
     41         int del(int index);
     42         int delete_first();
     43         int delete_last();
     44 
     45     private:
     46         int count;
     47         DNode<T> *phead;
     48     private:
     49         DNode<T> *get_node(int index);
     50 };
     51 
     52 template<class T>
     53 DoubleLink<T>::DoubleLink() : count(0)
     54 {
     55     // 创建“表头”。注意:表头没有存储数据!
     56     phead = new DNode<T>();
     57     phead->prev = phead->next = phead;
     58     // 设置链表计数为0
     59     //count = 0;
     60 }
     61 
     62 // 析构函数
     63 template<class T>
     64 DoubleLink<T>::~DoubleLink() 
     65 {
     66     // 删除所有的节点
     67     DNode<T>* ptmp;
     68     DNode<T>* pnode = phead->next;
     69     while (pnode != phead)
     70     {
     71         ptmp = pnode;
     72         pnode=pnode->next;
     73         delete ptmp;
     74     }
     75 
     76     // 删除"表头"
     77     delete phead;
     78     phead = NULL;
     79 }
     80 
     81 // 返回节点数目
     82 template<class T>
     83 int DoubleLink<T>::size() 
     84 {
     85     return count;
     86 }
     87 
     88 // 返回链表是否为空
     89 template<class T>
     90 int DoubleLink<T>::is_empty() 
     91 {
     92     return count==0;
     93 }
     94 
     95 // 获取第index位置的节点
     96 template<class T>
     97 DNode<T>* DoubleLink<T>::get_node(int index) 
     98 {
     99     // 判断参数有效性
    100     if (index<0 || index>=count)
    101     {
    102         cout << "get node failed! the index in out of bound!" << endl;
    103         return NULL;
    104     }
    105 
    106     // 正向查找
    107     if (index <= count/2)
    108     {
    109         int i=0;
    110         DNode<T>* pindex = phead->next;
    111         while (i++ < index) {
    112             pindex = pindex->next;
    113         }
    114 
    115         return pindex;
    116     }
    117 
    118     // 反向查找
    119     int j=0;
    120     int rindex = count - index -1;
    121     DNode<T>* prindex = phead->prev;
    122     while (j++ < rindex) {
    123         prindex = prindex->prev;
    124     }
    125 
    126     return prindex;
    127 }
    128 
    129 // 获取第index位置的节点的值
    130 template<class T>
    131 T DoubleLink<T>::get(int index) 
    132 {
    133     return get_node(index)->value;
    134 }
    135 
    136 // 获取第1个节点的值
    137 template<class T>
    138 T DoubleLink<T>::get_first() 
    139 {
    140     return get_node(0)->value;
    141 }
    142 
    143 // 获取最后一个节点的值
    144 template<class T>
    145 T DoubleLink<T>::get_last() 
    146 {
    147     return get_node(count-1)->value;
    148 }
    149 
    150 // 将节点插入到第index位置之前
    151 template<class T>
    152 int DoubleLink<T>::insert(int index, T t) 
    153 {
    154     if (index == 0)
    155         return insert_first(t);
    156 
    157     DNode<T>* pindex = get_node(index);
    158     DNode<T>* pnode  = new DNode<T>(t, pindex->prev, pindex);
    159     pindex->prev->next = pnode;
    160     pindex->prev = pnode;
    161     count++;
    162 
    163     return 0;
    164 }
    165 
    166 // 将节点插入第一个节点处。
    167 template<class T>
    168 int DoubleLink<T>::insert_first(T t) 
    169 {
    170     DNode<T>* pnode  = new DNode<T>(t, phead, phead->next);
    171     phead->next->prev = pnode;
    172     phead->next = pnode;
    173     count++;
    174 
    175     return 0;
    176 }
    177 
    178 // 将节点追加到链表的末尾
    179 template<class T>
    180 int DoubleLink<T>::append_last(T t) 
    181 {
    182     DNode<T>* pnode = new DNode<T>(t, phead->prev, phead);
    183     phead->prev->next = pnode;
    184     phead->prev = pnode;
    185     count++;
    186 
    187     return 0;
    188 }
    189 
    190 // 删除index位置的节点
    191 template<class T>
    192 int DoubleLink<T>::del(int index) 
    193 {
    194     DNode<T>* pindex = get_node(index);
    195     pindex->next->prev = pindex->prev;
    196     pindex->prev->next = pindex->next;
    197     delete pindex;
    198     count--;
    199 
    200     return 0;
    201 }
    202 
    203 // 删除第一个节点
    204 template<class T>
    205 int DoubleLink<T>::delete_first() 
    206 {
    207     return del(0);
    208 }
    209 
    210 // 删除最后一个节点
    211 template<class T>
    212 int DoubleLink<T>::delete_last() 
    213 {
    214     return del(count-1);
    215 }
    216 
    217 #endif
    View Code

    双向链表测试文件(DlinkTest.cpp)

      1 #include <iostream>
      2 #include "DoubleLink.h"
      3 using namespace std;
      4 
      5 // 双向链表操作int数据
      6 void int_test()
      7 {
      8     int iarr[4] = {10, 20, 30, 40};
      9 
     10     cout << "
    ----int_test----" << endl;
     11     // 创建双向链表
     12     DoubleLink<int>* pdlink = new DoubleLink<int>();
     13 
     14     pdlink->insert(0, 20);        // 将 20 插入到第一个位置
     15     pdlink->append_last(10);    // 将 10 追加到链表末尾
     16     pdlink->insert_first(30);    // 将 30 插入到第一个位置
     17 
     18     // 双向链表是否为空
     19     cout << "is_empty()=" << pdlink->is_empty() <<endl;
     20     // 双向链表的大小
     21     cout << "size()=" << pdlink->size() <<endl;
     22 
     23     // 打印双向链表中的全部数据
     24     int sz = pdlink->size();
     25     for (int i=0; i<sz; i++)
     26         cout << "pdlink("<<i<<")=" << pdlink->get(i) <<endl;
     27 }
     28 
     29 void string_test()
     30 {
     31     string sarr[4] = {"ten", "twenty", "thirty", "forty"};
     32 
     33     cout << "
    ----string_test----" << endl;
     34     // 创建双向链表
     35     DoubleLink<string>* pdlink = new DoubleLink<string>();
     36 
     37     pdlink->insert(0, sarr[1]);        // 将 sarr中第2个元素 插入到第一个位置
     38     pdlink->append_last(sarr[0]);    // 将 sarr中第1个元素  追加到链表末尾
     39     pdlink->insert_first(sarr[2]);    // 将 sarr中第3个元素  插入到第一个位置
     40 
     41     // 双向链表是否为空
     42     cout << "is_empty()=" << pdlink->is_empty() <<endl;
     43     // 双向链表的大小
     44     cout << "size()=" << pdlink->size() <<endl;
     45 
     46     // 打印双向链表中的全部数据
     47     int sz = pdlink->size();
     48     for (int i=0; i<sz; i++)
     49         cout << "pdlink("<<i<<")=" << pdlink->get(i) <<endl;
     50 }
     51 
     52 struct stu
     53 {
     54     int id;
     55     char name[20];
     56 };
     57 
     58 static stu arr_stu[] = 
     59 {
     60     {10, "sky"},
     61     {20, "jody"},
     62     {30, "vic"},
     63     {40, "dan"},
     64 };
     65 #define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) )
     66 
     67 void object_test()
     68 {
     69     cout << "
    ----object_test----" << endl;
     70     // 创建双向链表
     71     DoubleLink<stu>* pdlink = new DoubleLink<stu>();
     72 
     73     pdlink->insert(0, arr_stu[1]);        // 将 arr_stu中第2个元素 插入到第一个位置
     74     pdlink->append_last(arr_stu[0]);    // 将 arr_stu中第1个元素  追加到链表末尾
     75     pdlink->insert_first(arr_stu[2]);    // 将 arr_stu中第3个元素  插入到第一个位置
     76 
     77     // 双向链表是否为空
     78     cout << "is_empty()=" << pdlink->is_empty() <<endl;
     79     // 双向链表的大小
     80     cout << "size()=" << pdlink->size() <<endl;
     81 
     82     // 打印双向链表中的全部数据
     83     int sz = pdlink->size();
     84     struct stu p;
     85     for (int i=0; i<sz; i++) 
     86     {
     87         p = pdlink->get(i);
     88         cout << "pdlink("<<i<<")=[" << p.id << ", " << p.name <<"]" <<endl;
     89     }
     90 }
     91 
     92 
     93 int main()
     94 {
     95     int_test();        // 演示向双向链表操作“int数据”。
     96     string_test();    // 演示向双向链表操作“字符串数据”。
     97     object_test();    // 演示向双向链表操作“对象”。
     98 
     99     return 0;
    100 }
    View Code

    示例说明

    在上面的示例中,我将双向链表的"声明"和"实现"都放在头文件中。而编程规范告诫我们:将类的声明和实现分离,在头文件(.h文件或.hpp)中尽量只包含声明,而在实现文件(.cpp文件)中负责实现!
    那么为什么要这么做呢?这是因为,在双向链表的实现中,采用了模板;而C++编译器不支持对模板的分离式编译!简单点说,如果在DoubleLink.h中声明,而在DoubleLink.cpp中进行实现的话;当我们在其他类中创建DoubleLink的对象时,会编译出错。具体原因,可以参考"为什么C++编译器不能支持对模板的分离式编译"。


    运行结果

    ----int_test----
    is_empty()=0
    size()=3
    pdlink(0)=30
    pdlink(1)=20
    pdlink(2)=10
    
    ----string_test----
    is_empty()=0
    size()=3
    pdlink(0)=thirty
    pdlink(1)=twenty
    pdlink(2)=ten
    
    ----object_test----
    is_empty()=0
    size()=3
    pdlink(0)=[30, vic]
    pdlink(1)=[20, jody]
    pdlink(2)=[10, sky]

    3. Java实现双链表

    实现代码
    双链表类(DoubleLink.java)

      1 /**
      2  * Java 实现的双向链表。 
      3  * 注:java自带的集合包中有实现双向链表,路径是:java.util.LinkedList
      4  *
      5  * @author skywang
      6  * @date 2013/11/07
      7  */
      8 public class DoubleLink<T> {
      9 
     10     // 表头
     11     private DNode<T> mHead;
     12     // 节点个数
     13     private int mCount;
     14 
     15     // 双向链表“节点”对应的结构体
     16     private class DNode<T> {
     17         public DNode prev;
     18         public DNode next;
     19         public T value;
     20 
     21         public DNode(T value, DNode prev, DNode next) {
     22             this.value = value;
     23             this.prev = prev;
     24             this.next = next;
     25         }
     26     }
     27 
     28     // 构造函数
     29     public DoubleLink() {
     30         // 创建“表头”。注意:表头没有存储数据!
     31         mHead = new DNode<T>(null, null, null);
     32         mHead.prev = mHead.next = mHead;
     33         // 初始化“节点个数”为0
     34         mCount = 0;
     35     }
     36 
     37     // 返回节点数目
     38     public int size() {
     39         return mCount;
     40     }
     41 
     42     // 返回链表是否为空
     43     public boolean isEmpty() {
     44         return mCount==0;
     45     }
     46 
     47     // 获取第index位置的节点
     48     private DNode<T> getNode(int index) {
     49         if (index<0 || index>=mCount)
     50             throw new IndexOutOfBoundsException();
     51 
     52         // 正向查找
     53         if (index <= mCount/2) {
     54             DNode<T> node = mHead.next;
     55             for (int i=0; i<index; i++)
     56                 node = node.next;
     57 
     58             return node;
     59         }
     60 
     61         // 反向查找
     62         DNode<T> rnode = mHead.prev;
     63         int rindex = mCount - index -1;
     64         for (int j=0; j<rindex; j++)
     65             rnode = rnode.prev;
     66 
     67         return rnode;
     68     }
     69 
     70     // 获取第index位置的节点的值
     71     public T get(int index) {
     72         return getNode(index).value;
     73     }
     74 
     75     // 获取第1个节点的值
     76     public T getFirst() {
     77         return getNode(0).value;
     78     }
     79 
     80     // 获取最后一个节点的值
     81     public T getLast() {
     82         return getNode(mCount-1).value;
     83     }
     84 
     85     // 将节点插入到第index位置之前
     86     public void insert(int index, T t) {
     87         if (index==0) {
     88             DNode<T> node = new DNode<T>(t, mHead, mHead.next);
     89             mHead.next.prev = node;
     90             mHead.next = node;
     91             mCount++;
     92             return ;
     93         }
     94 
     95         DNode<T> inode = getNode(index);
     96         DNode<T> tnode = new DNode<T>(t, inode.prev, inode);
     97         inode.prev.next = tnode;
     98         inode.next = tnode;
     99         mCount++;
    100         return ;
    101     }
    102 
    103     // 将节点插入第一个节点处。
    104     public void insertFirst(T t) {
    105         insert(0, t);
    106     }
    107 
    108     // 将节点追加到链表的末尾
    109     public void appendLast(T t) {
    110         DNode<T> node = new DNode<T>(t, mHead.prev, mHead);
    111         mHead.prev.next = node;
    112         mHead.prev = node;
    113         mCount++;
    114     }
    115 
    116     // 删除index位置的节点
    117     public void del(int index) {
    118         DNode<T> inode = getNode(index);
    119         inode.prev.next = inode.next;
    120         inode.next.prev = inode.prev;
    121         inode = null;
    122         mCount--;
    123     }
    124 
    125     // 删除第一个节点
    126     public void deleteFirst() {
    127         del(0);
    128     }
    129 
    130     // 删除最后一个节点
    131     public void deleteLast() {
    132         del(mCount-1);
    133     }
    134 }
    View Code

    测试程序(DlinkTest.java)

      1 /**
      2  * Java 实现的双向链表。 
      3  * 注:java自带的集合包中有实现双向链表,路径是:java.util.LinkedList
      4  *
      5  * @author skywang
      6  * @date 2013/11/07
      7  */
      8 
      9 public class DlinkTest {
     10 
     11     // 双向链表操作int数据
     12     private static void int_test() {
     13         int[] iarr = {10, 20, 30, 40};
     14 
     15         System.out.println("
    ----int_test----");
     16         // 创建双向链表
     17         DoubleLink<Integer> dlink = new DoubleLink<Integer>();
     18 
     19         dlink.insert(0, 20);    // 将 20 插入到第一个位置
     20         dlink.appendLast(10);    // 将 10 追加到链表末尾
     21         dlink.insertFirst(30);    // 将 30 插入到第一个位置
     22 
     23         // 双向链表是否为空
     24         System.out.printf("isEmpty()=%b
    ", dlink.isEmpty());
     25         // 双向链表的大小
     26         System.out.printf("size()=%d
    ", dlink.size());
     27 
     28         // 打印出全部的节点
     29         for (int i=0; i<dlink.size(); i++)
     30             System.out.println("dlink("+i+")="+ dlink.get(i));
     31     }
     32 
     33 
     34     private static void string_test() {
     35         String[] sarr = {"ten", "twenty", "thirty", "forty"};
     36 
     37         System.out.println("
    ----string_test----");
     38         // 创建双向链表
     39         DoubleLink<String> dlink = new DoubleLink<String>();
     40 
     41         dlink.insert(0, sarr[1]);    // 将 sarr中第2个元素 插入到第一个位置
     42         dlink.appendLast(sarr[0]);    // 将 sarr中第1个元素 追加到链表末尾
     43         dlink.insertFirst(sarr[2]);    // 将 sarr中第3个元素 插入到第一个位置
     44 
     45         // 双向链表是否为空
     46         System.out.printf("isEmpty()=%b
    ", dlink.isEmpty());
     47         // 双向链表的大小
     48         System.out.printf("size()=%d
    ", dlink.size());
     49 
     50         // 打印出全部的节点
     51         for (int i=0; i<dlink.size(); i++)
     52             System.out.println("dlink("+i+")="+ dlink.get(i));
     53     }
     54 
     55 
     56     // 内部类
     57     private static class Student {
     58         private int id;
     59         private String name;
     60 
     61         public Student(int id, String name) {
     62             this.id = id;
     63             this.name = name;
     64         }
     65 
     66         @Override
     67         public String toString() {
     68             return "["+id+", "+name+"]";
     69         }
     70     }
     71 
     72     private static Student[] students = new Student[]{
     73         new Student(10, "sky"),
     74         new Student(20, "jody"),
     75         new Student(30, "vic"),
     76         new Student(40, "dan"),
     77     };
     78 
     79     private static void object_test() {
     80         System.out.println("
    ----object_test----");
     81         // 创建双向链表
     82         DoubleLink<Student> dlink = new DoubleLink<Student>();
     83 
     84         dlink.insert(0, students[1]);    // 将 students中第2个元素 插入到第一个位置
     85         dlink.appendLast(students[0]);    // 将 students中第1个元素 追加到链表末尾
     86         dlink.insertFirst(students[2]);    // 将 students中第3个元素 插入到第一个位置
     87 
     88         // 双向链表是否为空
     89         System.out.printf("isEmpty()=%b
    ", dlink.isEmpty());
     90         // 双向链表的大小
     91         System.out.printf("size()=%d
    ", dlink.size());
     92 
     93         // 打印出全部的节点
     94         for (int i=0; i<dlink.size(); i++) {
     95             System.out.println("dlink("+i+")="+ dlink.get(i));
     96         }
     97     }
     98 
     99  
    100     public static void main(String[] args) {
    101         int_test();        // 演示向双向链表操作“int数据”。
    102         string_test();    // 演示向双向链表操作“字符串数据”。
    103         object_test();    // 演示向双向链表操作“对象”。
    104     }
    105 }
    View Code


    运行结果

    ----int_test----
    isEmpty()=false
    size()=3
    dlink(0)=30
    dlink(1)=20
    dlink(2)=10
    
    ----string_test----
    isEmpty()=false
    size()=3
    dlink(0)=thirty
    dlink(1)=twenty
    dlink(2)=ten
    
    ----object_test----
    isEmpty()=false
    size()=3
    dlink(0)=[30, vic]
    dlink(1)=[20, jody]
    dlink(2)=[10, sky]

     

  • 相关阅读:
    更改sql server数据库所有者的对象
    对C#委托及事件委托的理解
    印度人是怎样开发软件的?
    SQL常用函数
    Ajax学习1
    Ajax学习2
    什么是ORM?
    jQuery 移动网页到制定的位置
    Juery 控件的取值赋值
    js禁用滚动条
  • 原文地址:https://www.cnblogs.com/skywang12345/p/3561803.html
Copyright © 2020-2023  润新知