链表(2)

:first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px}iframe{border:0}figure{-webkit-margin-before:0;-webkit-margin-after:0;-webkit-margin-start:0;-webkit-margin-end:0}kbd{border:1px solid #aaa;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:1px 2px 2px #ddd;-webkit-box-shadow:1px 2px 2px #ddd;box-shadow:1px 2px 2px #ddd;background-color:#f9f9f9;background-image:-moz-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:-o-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:-webkit-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:linear-gradient(top,#eee,#f9f9f9,#eee);padding:1px 3px;font-family:inherit;font-size:.85em}.oembeded .oembed_photo{display:inline-block}img[data-echo]{margin:25px 0;width:100px;height:100px;background:url(../img/ajax.gif) center center no-repeat #fff}.spinner{display:inline-block;width:10px;height:10px;margin-bottom:-.1em;border:2px solid rgba(0,0,0,.5);border-top-color:transparent;border-radius:100%;-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}.spinner:after{content:‘‘;display:block;width:0;height:0;position:absolute;top:-6px;left:0;border:4px solid transparent;border-bottom-color:rgba(0,0,0,.5);-webkit-transform:rotate(45deg);transform:rotate(45deg)}@-webkit-keyframes spin{to{-webkit-transform:rotate(360deg)}}@keyframes spin{to{transform:rotate(360deg)}}p.toc{margin:0!important}p.toc ul{padding-left:10px}p.toc>ul{padding:10px;margin:0 10px;display:inline-block;border:1px solid #ededed;border-radius:5px}p.toc li,p.toc ul{list-style-type:none}p.toc li{width:100%;padding:0;overflow:hidden}p.toc li a::after{content:"."}p.toc li a:before{content:"? "}p.toc h5{text-transform:uppercase}p.toc .title{float:left;padding-right:3px}p.toc .number{margin:0;float:right;padding-left:3px;background:#fff;display:none}input.task-list-item{margin-left:-1.62em}.markdown{font-family:"Hiragino Sans GB","Microsoft YaHei",stheiti,simsun,"Lucida Grande","Lucida Sans Unicode","Lucida Sans",‘Segoe UI‘,applesdgothicneo-medium,‘Malgun Gothic‘,verdana,tahoma,sans-serif;padding:20px}.markdown a{text-decoration:none;vertical-align:baseline}.markdown a:hover{text-decoration:underline}.markdown h1{font-size:2.2em;font-weight:700;margin:1.5em 0 1em}.markdown h2{font-size:1.8em;font-weight:700;margin:1.275em 0 .85em}.markdown h3{font-size:1.6em;font-weight:700;margin:1.125em 0 .75em}.markdown h4{font-size:1.4em;font-weight:700;margin:.99em 0 .66em}.markdown h5{font-size:1.2em;font-weight:700;margin:.855em 0 .57em}.markdown h6{font-size:1em;font-weight:700;margin:.75em 0 .5em}.markdown h1+p,.markdown h1:first-child,.markdown h2+p,.markdown h2:first-child,.markdown h3+p,.markdown h3:first-child,.markdown h4+p,.markdown h4:first-child,.markdown h5+p,.markdown h5:first-child,.markdown h6+p,.markdown h6:first-child{margin-top:0}.markdown hr{border:1px solid #ccc}.markdown p{margin:1em 0;word-wrap:break-word}.markdown ol{list-style-type:decimal}.markdown li{display:list-item;line-height:1.4em}.markdown blockquote{margin:1em 20px}.markdown blockquote>:first-child{margin-top:0}.markdown blockquote>:last-child{margin-bottom:0}.markdown blockquote cite:before{content:‘\2014 \00A0‘}.markdown .code{border-radius:3px;word-wrap:break-word}.markdown pre{border-radius:3px;word-wrap:break-word;border:1px solid #ccc;overflow:auto;padding:.5em}.markdown pre code{border:0;display:block}.markdown pre>code{font-family:consolas,inconsolata,courier,monospace;font-weight:700;white-space:pre;margin:0}.markdown code{border-radius:3px;word-wrap:break-word;border:1px solid #ccc;padding:0 5px;margin:0 2px}.markdown img{max-width:100%}.markdown mark{color:#000;background-color:#fcf8e3}.markdown table{padding:0;border-collapse:collapse;border-spacing:0;margin-bottom:16px}.markdown table tr td,.markdown table tr th{border:1px solid #ccc;margin:0;padding:6px 13px}.markdown table tr th{font-weight:700}.markdown table tr th>:first-child{margin-top:0}.markdown table tr th>:last-child{margin-bottom:0}.markdown table tr td>:first-child{margin-top:0}.markdown table tr td>:last-child{margin-bottom:0}@import url(http://fonts.googleapis.com/css?family=Roboto+Condensed:300italic,400italic,700italic,400,300,700);.haroopad{padding:20px;color:#222;font-size:15px;font-family:"Roboto Condensed",tauri,"Hiragino Sans GB","Microsoft YaHei",stheiti,simsun,"Lucida Grande","Lucida Sans Unicode","Lucida Sans",‘Segoe UI‘,applesdgothicneo-medium,‘Malgun Gothic‘,verdana,tahoma,sans-serif;background:#fff;line-height:1.6;-webkit-font-smoothing:antialiased}.haroopad a{color:#3269a0}.haroopad a:hover{color:#4183c4}.haroopad h2{border-bottom:1px solid #e6e6e6}.haroopad h6{color:#777}.haroopad hr{border:1px solid #e6e6e6}.haroopad blockquote>code,.haroopad h1>code,.haroopad h2>code,.haroopad h3>code,.haroopad h4>code,.haroopad h5>code,.haroopad h6>code,.haroopad li>code,.haroopad p>code,.haroopad td>code{font-family:consolas,"Liberation Mono",menlo,courier,monospace;font-size:85%;background-color:rgba(0,0,0,.02);padding:.2em .5em;border:1px solid #efefef}.haroopad pre>code{font-size:1em;letter-spacing:-1px;font-weight:700}.haroopad blockquote{border-left:4px solid #e6e6e6;padding:0 15px;color:#777}.haroopad table{background-color:#fafafa}.haroopad table tr td,.haroopad table tr th{border:1px solid #e6e6e6}.haroopad table tr:nth-child(2n){background-color:#f2f2f2}.hljs{display:block;overflow-x:auto;padding:.5em;background:#23241f;-webkit-text-size-adjust:none}.aspectj .hljs-function,.css .hljs-function .hljs-preprocessor,.css .hljs-rules,.css .hljs-value,.hljs,.hljs-pragma,.hljs-tag{color:#f8f8f2}.hljs-emphasis,.hljs-strong,.hljs-strongemphasis{color:#a8a8a2}.alias .hljs-keyword,.hljs-blockquote,.hljs-bullet,.hljs-hexcolor,.hljs-horizontal_rule,.hljs-literal,.hljs-number,.hljs-regexp{color:#ae81ff}.css .hljs-class,.hljs-class .hljs-title:last-child,.hljs-code,.hljs-tag .hljs-value,.hljs-title{color:#a6e22e}.hljs-link_url{font-size:80%}.hljs-strong,.hljs-strongemphasis{font-weight:700}.hljs-class .hljs-title:last-child,.hljs-emphasis,.hljs-strongemphasis,.hljs-typename{font-style:italic}.alias .hljs-keyword:first-child,.css .hljs-important,.css .hljs-tag,.css .unit,.hljs-attribute,.hljs-change,.hljs-flow,.hljs-function,.hljs-header,.hljs-keyword,.hljs-symbol,.hljs-symbol .hljs-string,.hljs-tag .hljs-title,.hljs-value,.hljs-winutils,.nginx .hljs-title,.ruby .hljs-class .hljs-keyword:first-child,.ruby .hljs-function .hljs-keyword,.tex .hljs-special{color:#f92672}.css .hljs-attribute,.hljs-aspect .hljs-keyword:first-child,.hljs-class .hljs-keyword:first-child,.hljs-constant,.hljs-function .hljs-keyword,.hljs-typename{color:#66d9ef}.hljs-aspect .hljs-title,.hljs-class .hljs-title,.hljs-params,.hljs-variable{color:#f8f8f2}.apache .hljs-cbracket,.apache .hljs-tag,.css .hljs-id,.django .hljs-filter .hljs-argument,.django .hljs-template_tag,.django .hljs-variable,.hljs-addition,.hljs-attr_selector,.hljs-built_in,.hljs-envvar,.hljs-link_label,.hljs-link_url,.hljs-prompt,.hljs-pseudo,.hljs-stream,.hljs-string,.hljs-subst,.hljs-type,.ruby .hljs-class .hljs-parent,.smalltalk .hljs-array,.smalltalk .hljs-class,.smalltalk .hljs-localvars,.tex .hljs-command{color:#e6db74}.apache .hljs-sqbracket,.hljs-annotation,.hljs-comment,.hljs-decorator,.hljs-deletion,.hljs-doctype,.hljs-javadoc,.hljs-pi,.hljs-shebang,.tex .hljs-formula{color:#75715e}.coffeescript .javascript,.javascript .xml,.php .xml,.tex .hljs-formula,.xml .css,.xml .hljs-cdata,.xml .javascript,.xml .php,.xml .vbscript{opacity:.5}.mathjax_hover_frame{border-radius:.25em;-webkit-border-radius:.25em;-moz-border-radius:.25em;-khtml-border-radius:.25em;box-shadow:0 0 15px #83a;-webkit-box-shadow:0 0 15px #83a;-moz-box-shadow:0 0 15px #83a;-khtml-box-shadow:0 0 15px #83a;border:1px solid #a6d!important;display:inline-block;position:absolute}.mathjax_hover_arrow{position:absolute;width:15px;height:11px;cursor:pointer}#mathjax_about{position:fixed;left:50%;width:auto;text-align:center;border:3px outset;padding:1em 2em;background-color:#ddd;color:#000;cursor:default;font-family:message-box;font-size:120%;font-style:normal;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;z-index:201;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;-khtml-border-radius:15px;box-shadow:0 10px 20px gray;-webkit-box-shadow:0 10px 20px gray;-moz-box-shadow:0 10px 20px gray;-khtml-box-shadow:0 10px 20px gray;filter:progid:dximagetransform.microsoft.dropshadow(offx=2, offy=2, color=‘gray‘, positive=‘true‘)}.mathjax_menu{position:absolute;background-color:#fff;color:#000;width:auto;padding:2px;border:1px solid #ccc;margin:0;cursor:default;font:menu;text-align:left;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;z-index:201;box-shadow:0 10px 20px gray;-webkit-box-shadow:0 10px 20px gray;-moz-box-shadow:0 10px 20px gray;-khtml-box-shadow:0 10px 20px gray;filter:progid:dximagetransform.microsoft.dropshadow(offx=2, offy=2, color=‘gray‘, positive=‘true‘)}.mathjax_menuitem{padding:2px 2em;background:0 0}.mathjax_menuarrow{position:absolute;right:.5em;color:#666}.mathjax_menuactive .mathjax_menuarrow{color:#fff}.mathjax_menuarrow.rtl{left:.5em;right:auto}.mathjax_menucheck{position:absolute;left:.7em}.mathjax_menucheck.rtl{right:.7em;left:auto}.mathjax_menuradiocheck{position:absolute;left:1em}.mathjax_menuradiocheck.rtl{right:1em;left:auto}.mathjax_menulabel{padding:2px 2em 4px 1.33em;font-style:italic}.mathjax_menurule{border-top:1px solid #ccc;margin:4px 1px 0}.mathjax_menudisabled{color:graytext}.mathjax_menuactive{background-color:highlight;color:highlighttext}.mathjax_menu_close{position:absolute;width:31px;height:31px;top:-15px;left:-15px}#mathjax_zoom{position:absolute;background-color:#f0f0f0;overflow:auto;display:block;z-index:301;padding:.5em;border:1px solid #000;margin:0;font-weight:400;font-style:normal;text-align:left;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;box-shadow:5px 5px 15px #aaa;-webkit-box-shadow:5px 5px 15px #aaa;-moz-box-shadow:5px 5px 15px #aaa;-khtml-box-shadow:5px 5px 15px #aaa;filter:progid:dximagetransform.microsoft.dropshadow(offx=2, offy=2, color=‘gray‘, positive=‘true‘)}#mathjax_zoomoverlay{position:absolute;left:0;top:0;z-index:300;display:inline-block;width:100%;height:100%;border:0;padding:0;margin:0;background-color:#fff;opacity:0;filter:alpha(opacity=0)}#mathjax_zoomframe{position:relative;display:inline-block;height:0;width:0}#mathjax_zoomeventtrap{position:absolute;left:0;top:0;z-index:302;display:inline-block;border:0;padding:0;margin:0;background-color:#fff;opacity:0;filter:alpha(opacity=0)}.mathjax_preview{color:#888}#mathjax_message{position:fixed;left:1px;bottom:2px;background-color:#e6e6e6;border:1px solid #959595;margin:0;padding:2px 8px;z-index:102;color:#000;font-size:80%;width:auto;white-space:nowrap}#mathjax_msie_frame{position:absolute;top:0;left:0;width:0;z-index:101;border:0;margin:0;padding:0}.mathjax_error{color:#c00;font-style:italic}footer{position:fixed;font-size:.8em;text-align:right;bottom:0;margin-left:-25px;height:20px;width:100%}
-->

链表(2)

我们在链表1中探讨了链表的一些最基本最简单的一些用法,只能用来讲讲链表操作的基本原理,不具有通用性。

事实上,我们在实际的项目中用的是在nginx内核中的一种通用的循环链表,其完全是由C语言的宏来定义的,设计非常的简洁巧妙,用在生产环境非常的健壮稳固。

在讲通用链表之前先讲一个宏:offsetof()

size_t offsetof(structName, memberName);

其表示为某结构体成员相对于其所在结构体的中偏移量。通用链表的实现就依赖于这个宏实现的。
下面来介绍nginx通用双向链表的结构体定义

typedef struct ngx_queue_s  ngx_queue_t;

struct ngx_queue_s {
    ngx_queue_t  *prev;
    ngx_queue_t  *next;
};

其定义非常的简单,仅仅是两个指向前节点和后节点的指针。ngx_queue_t 作为结构体的子成员,如:

struct userinfo{
    char * firstname;
    char * lastname;
    int age;
    int sex;
    ngx_queue_t queue;
}

所有关于链表的操作,都是对ngx_queue_t的操作,当我们要取得userinfo结构体地址时,就可以用上面的offsetof宏,根据queue的地址来取得了,理论上来说,一个ngx_queue_t的链表可以串起包含有ngx_queue_t的任意结构体类型,但是建议还是像C++或者java,csharp的泛型一样,一个链表中只包含一种结构体类型。

实际项目中,我们对其进行重新命名,并进行了封装,详见源码目录下的core/na_queue.h
其具体代码如下:

/*
 * Copyright(C) Neo
 * Thu Mar 28 11:30:44 2013
 * 对列定义(双向队列,环形队列) 参考nigix队列定义,以及Linux内核队列定义
 */

#ifndef _NA_QUEUE_H_
#define _NA_QUEUE_H_

#include "na_core.h"

typedef struct na_queue_s na_queue_t;

struct na_queue_s {
  na_queue_t * prev;
  na_queue_t * next;
};

/* 初始化队列 */
#define na_queue_init(q)                      \
  (q)->prev = (q);          (q)->next = (q)

/* 判断队列是否为空 */
#define na_queue_empty(h) \
  ((h) == (h)->prev)

/* 从头插入节点 */
#define na_queue_insert_head(h,x)     \
  (x)->next = (h)->next;                (x)->next->prev = (x);                (x)->prev = (h);                      (h)->next = (x)

#define na_queue_insert_after na_queue_insert_head

/* 从末尾插入节点 */
#define na_queue_insert_tail(h,x)      \
  (x)->prev = (h)->prev;                 (x)->prev->next = x;                   (x)->next = h;                         (h)->prev = x 

/* 头指针对应的头节点 */
#define na_queue_head(h) (h)->next

/* 最后一个节点 */
#define na_queue_last(h) (h)->prev

#define na_queue_sentinel(h) (h)

/*下一个节点*/
#define na_queue_next(q) (q)->next

/* 前一个节点 */
#define na_queue_prev(q) (q)->prev

/* 移除一个节点 */
#define na_queue_remove(x)             \
  (x)->next->prev = (x)->prev;           (x)->prev->next = (x)->next;           (x)->prev = NULL;                      (x)->next = NULL

/* 切分一个队列
 * h 头指针
 * q 需要拆分的头指针
 * n 拆分完成后另外一个队列的头指针
 */
#define na_queue_split(h,q,n)           \
    (n)->prev = (h)->prev;                  (n)->prev->next = n;                    (n)->next = q;                          (h)->prev = (q)->prev;                  (h)->prev->next = h;                    (q)->prev = n;

/* 合并两个队列 */
#define na_queue_add(h,n)               \
  (h)->prev->next = (n)->next;            (n)->next->prev = (h)->prev;            (h)->prev = (n)->prev;                  (h)->prev->next = (h);

/* 根据队列指针,得到包涵此队列指针的结构体
 * q 队列指针
 * type 返回的数据类型
 * link 数据项中对应的队列项名字
 */
#define na_queue_data(q, type, link)   \
    (type *) ((u_char *) q - offsetof(type, link))

/* 查找中间节点 */
na_queue_t *
na_queue_middle(na_queue_t * queue);

/* 对队列排序 */
void na_queue_sort(na_queue_t *queue,int (*cmp)(const na_queue_t *, const na_queue_t *));

/*遍历队列中节点的数据
 *q:传入的包含队列类型的结构体指针
 *s:队列的哨兵指针
 *type:包含队列的结构体类型
 *link:队列在结构体中的名字
*/
#define na_queue_foreach(q,s,type,link)          \
  na_queue_t * _head_ =NULL;                           for(_head_=na_queue_head(s),q=na_queue_data(_head_,type,link);_head_!=s;_head_=na_queue_next(_head_),q=na_queue_data(_head_,type,link))

// add by hc
#define NA_QUEUE_INIT(name) {&(name),&(name)}
#define na_queue_is_last(head,node) ((node)->next == (head))
#define na_queue_for_each(pos,head) \
    for(pos = (head)->next;pos != head;pos = pos->next)
#define na_queue_for_each_safe(pos,n,head) \
    for(pos = (head)->next,n = pos->next;pos != (head);pos = n,n = pos->next)

#endif /* _NA_QUEUE_H_ */

其链表的操作

函数名 参数说明 函数执行意义
na_queue_init 哨兵节点 初始化链表的哨兵节点
na_queue_empty 同上 判断链表是否为空
na_queue_insert_head   在表头插入节点
na_queue_insert_after   在表尾插入节点
na_queue_head   取得链表表头
na_queue_last   取得表尾
na_queue_sentinel   取得哨兵节点
na_queue_next   取得下一个节点
na_queue_prev   取得前一个节点
na_queue_remove   移除一个节点
na_queue_split   拆分一个链表
na_queue_add   合并一个链表
na_queue_data q 队列指针 type 返回的数据类型 link 数据项中对应的队列项名字 根据队列指针,得到包涵此队列指针的结构体
na_queue_middle   查找中间节点
na_queue_sort   对队列排序
na_queue_foreach q:传入的包含队列类型的结构体指针 s:队列的哨兵指针 type:包含队列的结构体类型 link:队列在结构体中的名字 遍历队列中节点的数据
na_queue_for_each_safe   安全遍历队列中节点的数据

其他参数说明见源码说明,
这里重点讲两个宏 na_queue_datena_queue_foreach

na_queue_date 是最上面offsetof宏的应用,功能是取得包含链表指针的结构体的地址。

na_queue_foreach 是遍历队列中的所有的节点

下面通过一个简单的插入排序来展示链表的用法:

#include <stdio.h>
#include <stdlib.h>
#include "na_queue.h"
#include <time.h>

typedef struct  number_s number_t;
typedef unsigned char u_char;
struct number_s{
        int value;
        na_queue_t queue;
};

//根据一个int值新建一个节点
number_t *
new_number_t(int v){
        number_t * n = calloc(sizeof(number_t),1);
        n->value = v;
        return n;
}
//释放一个number_t的链表中所有节点
void free_number_t(na_queue_t * h){
        na_queue_t * p = h->next;
        while(p!=h){
                na_queue_remove(p);
                number_t* q =na_queue_data(p,number_t,queue);
                free(q);
                p = h->next;
        }
}

//打印一个链表的所有节点值
void
print_queue(na_queue_t * h){
        na_queue_t * p = h->next;
        while(p!=h){
                number_t * q = na_queue_data(p,number_t,queue);
                printf("%d ",q->value);
                p=p->next;
        }
        printf("\n");
}

//在链表中插入一个值,使其按照从小到大顺序排列
void
insert_node(na_queue_t * h,int v){
        number_t * n= new_number_t(v);
        if(na_queue_empty(h)){
               na_queue_insert_tail(h,&n->queue);
               return;
        }
        na_queue_t * p = h->next;
        while(p!=h){
               number_t * num = na_queue_data(p,number_t,queue);
               if(num->value > v){
                       na_queue_t* q = na_queue_prev(p);
                       na_queue_t* c = &n->queue;
                       na_queue_next(q) = c;
                       na_queue_next(c) = p;
                       na_queue_prev(c) = q;
                       na_queue_prev(p) = c;
                       return;
               }
               p = na_queue_next(p);
        }
        na_queue_insert_tail(h,&n->queue);

}

//得到一个随机数
int get_random(){
        srand(time(0));
        return rand()/100000000;
}

int main(int argc, char *argv[])
{
        na_queue_t h;
        na_queue_init(&h);
        int i;
        for (i = 0; i < 10; i++) {
                int r = get_random();
                printf("add number:%d\n",r);
                insert_node(&h,r);
                print_queue(&h);
                sleep(1);
        }
        free_number_t(&h);
        return 0;
}

测试时一段插入排序程序,输出如下:
add number:10

10

add number:18

10 18

add number:4

4 10 18

add number:1

1 4 10 18

add number:20

1 4 10 18 20

add number:17

1 4 10 17 18 20

add number:3

1 3 4 10 17 18 20

add number:0

0 1 3 4 10 17 18 20

add number:18

0 1 3 4 10 17 18 18 20

add number:5

0 1 3 4 5 10 17 18 18 20

事实上最开始见到这个链表结构是从Linux内核代码中,位于<linux/list.h>

其更是广泛应用于Linux内核中,在Linux驱动程序设计的也会用到,有机会写关于Linux驱动设计的文章时,我们再举例了。



参考文献:

  1. 《Linux内核设计与实现》(Linux Kernel Development Third Edition) Robert Love
  2. 《深入理解Nginx》模块化开发与架构解析
  3. 《算法导论》

generated by haroopad

时间: 2024-10-20 18:18:34

链表(2)的相关文章

c语言动态链表的创建

创建动态连链表就是将一个个节点连接起来 (1)动态生成节点 (2)输入节点数据 (3)将节点链在一起 例: typedef struct Data { char num[20]; char name[10]; char sex; float english; float chinese; float math; }; typedef struct Node { struct Data data;//结构体类型//结构体嵌套 struct Node* next;//结构体指针型 }node,*Pn

算法学习——单链表快排

/**  * 以p为轴对start-end间的节点进行快排(包括start && 不包括end):  * 思路:  * 1.将头节点作为轴节点start,从start.next开始遍历,如果节点小于轴start的值,将该节点插入到轴节点后面:  * 2.将轴节点插入合适位置,即找到最后一个小于轴的节点,将该节点与轴节点值互换,此时就链表分为两部分,小于轴节点和大于轴节点:  * 3.递归的遍历2中两部分节点.  *   * @param p  * @param start  * @para

【数据结构】之散列链表(Java语言描述)

散列链表,在JDK中的API实现是 HashMap 类. 为什么HashMap被称为"散列链表"?这与HashMap的内部存储结构有关.下面将根据源码进行分析. 首先要说的是,HashMap中维护着的是一个数组: transient Node<K,V>[] table; ,数组中的每个元素都是一个 Node 对象.这里的Node是HashMap的一个内部类,代码如下: static class Node<K,V> implements Map.Entry<

单链表逆置

重写单链表逆置,熟能生巧- #include <iostream> #include <cstdlib> using namespace std; typedef struct List{ int num; struct List *next; }ListNode,*pListNode; void display(ListNode *pHead) { while(pHead) { cout<<pHead->num<<"--"; pH

java-------单链表

单链表: * 1.链表可以是一种有序或无序的列表 * 2.链表的内容通常存储在内存中分散的为止 * 3.链表由节点组成,每一个节点具有相同的结构 * 4.节点分为数据域和链域,数据域存放节点内容,链域存放下一个节点的指针 package myLinkList; public class MyLinkedList<T> { /** *Node:节点对象 * 包括数据域data和链域next(指向下一个节点对象) */ class Node { private T data; private No

数据结构之链表

---恢复内容开始--- 1:有头节点.单向.不循环链表 对于这种有头节点的单向不循环链表插入数据如下图: 1)头部插入 2)尾部插入 代码如下 : 1 #include "stdafx.h" 2 #include<iostream> 3 4 using namespace std; 5 6 typedef int DATA; 7 typedef struct node* LIST; 8 9 struct node 10 { 11 DATA data; 12 struct

拿java写了一个有点像指针的单链表

public class LinkList { private Node firstNode; private Integer position; public LinkList() {  super(); } public LinkList(Node firstNode) {  super();  this.firstNode = firstNode; } public Node getFirstNode() {  return firstNode; } public void setFirs

02 单链表

线性表之链式存储---单链表 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 // 数据结构 6 typedef struct node 7 { 8 int data; 9 struct node *next; 10 }linkList; 11 12 // 创建单链表,并初始化 13 linkList *linkList_init(void) 14 { 15 linkList *l

(单链表)单链表的整体逆序和局部逆序

题目一:将单链表翻转. 思路:有三种方式. 一:用数组存储单链表的值,然后重新逆序赋值,效率较低. 二:利用三个指针,在原来的基础上进行逆序.这种方法比较实用,效率也高. 三:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾.需要新建一个链表,这种方法和第二种差不多. 这里我就写出第二种方法,比较实用. 代码(方法二): struct ListNode { int val; ListNode *next; ListNode(int x) :

链表操作法则之逆向遍历与倒置算法

一.创建链表: 对链表进行操作的所有算法的前提,就是我们首先要创建一个链表,我们可以选择正向建链和逆向建链: (一).正向建链: 首先,我们得自定义节点类型: typedef struct Node { int data;//数据域 struct Node * pNext;//指针域 }NODE,*PNODE; 通过数组进行链表数据域的赋值: int main (void) { PNODE pHead;//头指针,接收创建链表时返回的头结点地址 int a[8] = {12,37,49,65,2