子节点 父节点 下级节点

本文介绍了一种兼容性良好的方法来获取DOM树中的特定节点,这种方法尤其关注于解决不同浏览器之间的兼容性问题。文中详细解释了如何使用firstElementChild、lastElementChild、nextElementSibling及previousElementSibling等属性来准确地定位DOM树中的元素,并提供了一个适用于IE6及以上版本浏览器的示例代码。
        </head>
        <!--
         var u1 = u.childNodes.length; // 11  此方法浏览器的兼容性很差   但是我测试过现在都是一样的
         alert(u1);
         通过标签来取  parentNode  父节点   firstChild 首节点    lastChild 尾节点
         nextSibling   相同节点树层级的下一个节点     previousSibling   返回位于相同节点树层级的前一个元素

         firstChild,lastChild,nextSibling,previousSibling都会将空格或者换行当做节点处理,但是有代替属性

        所以为了准确地找到相应的元素,会用

        firstElementChild,

        lastElementChild,

        nextElementSibling,

        previousElementSibling

        兼容的写法,这是JavaScript自带的属性。

        但坏消息是IE6,7,8不兼容这些属性。IE9以上和火狐谷歌支持。

        于是我写了一个接口口,测试能在包括ie6在内运行的函数(自己写的,不知有没有其他什么细节错误没注意,反正能运行并且过滤文本节点获取正确的下一个元素节点)
        -->
        <body>
        <ul id = "ul01">
            <li id="id1">001</li>
            <li id="id2">002</li>
            <li id="id3">003</li>
            <li id="id4">004</li>
            <li id="id5">005</li>
        </ul>
        <script type="text/javascript">
             var s = document.getElementById("id4");
             var s1 = s.nextElementSibling;
            alert(s1.id) ;
        </script>
        </body>

<think>我们要求不使用尾节点(即不维护尾指针)来实现尾插法。通常尾插法需要尾指针来指向链表的最后节点,以便在尾部高效插入。如果不使用尾指针,那么每次插入都需要从头遍历到尾部,这样时间复杂度会变为$O(n)$,其中$n$是当前链表的长度。虽然效率较低,但可以实现。 修改思路: 1. 初始化个带头节点的空链表,头节点的next为NULL。 2. 对于每个输入的数值(直到-1为止): a. 创建个新节点s,并赋值。 b. 由于没有尾指针,我们需要从链表的头节点开始遍历,直到找到最后节点(即当前链表的尾节点)。 c. 将最后节点的next指向新节点。 注意:在每次插入时,我们都要遍历整个链表找到尾节点,所以如果链表当前有n个节点,则插入第n+1个节点需要遍历n个节点,总的时间复杂度为$O(n^2)$。 具体修改: 在Create函数中: - 删除尾指针tail(即不使用尾指针) - 在每次插入新节点时,循环遍历链表找到尾节点,然后将新节点链接到尾节点后面。 代码如下(注释部分为修改或新增的代码): </think>### 不使用尾节点的尾插法实现方案 在不使用尾指针的情况下实现尾插法,需要通过每次遍历链表找到尾部节点进行插入。以下是修改后的代码实现: ```c LinkList Create() { LinkList L, p, s; // 不再使用尾指针tail ElemType e; // 创建头结点 L = (LinkList)malloc(sizeof(LNode)); if (L == NULL) return NULL; L->next = NULL; printf("输入元素(-1结束): "); scanf("%d", &e); while (e != -1) { s = (LinkList)malloc(sizeof(LNode)); if (s == NULL) break; s->data = e; s->next = NULL; /** 关键修改:遍历找到尾部节点 **/ p = L; // 从头结点开始遍历 while (p->next != NULL) { // 找到当前链表尾部 p = p->next; } p->next = s; // 在尾部插入新节点[^4] scanf("%d", &e); } return L; } ``` #### 算法复杂度分析 设链表长度为$n$: - **时间复杂度**:$O(n^2)$ - 插入第$k$个节点需要遍历$k-1$次 - 总操作次数:$\sum_{k=1}^{n} (k-1) = \frac{n(n-1)}{2}$ - **空间复杂度**:$O(1)$(仅需固定数量指针) #### 内存结构示意图(输入序列:2→4→6) ```mermaid graph LR L[头结点] --> 2 2 --> 4 4 --> 6 6 --> NULL classDef head fill:#f9f,stroke:#333; class L head; ``` #### 完整可运行代码 ```c #include <stdio.h> #include <stdlib.h> typedef int ElemType; typedef struct LNode { ElemType data; struct LNode *next; } LNode, *LinkList; LinkList Create(); void print(LinkList L); void Destroy(LinkList L); int main() { LinkList L = Create(); printf("创建结果: "); print(L); Destroy(L); return 0; } LinkList Create() { LinkList L, p, s; ElemType e; L = (LinkList)malloc(sizeof(LNode)); if (L == NULL) return NULL; L->next = NULL; printf("输入元素(-1结束): "); scanf("%d", &e); while (e != -1) { s = (LinkList)malloc(sizeof(LNode)); if (s == NULL) break; s->data = e; s->next = NULL; // 遍历找到尾部节点 p = L; while (p->next != NULL) { p = p->next; } p->next = s; // 尾部插入 scanf("%d", &e); } return L; } void print(LinkList L) { LinkList p = L->next; while (p) { printf("%d → ", p->data); p = p->next; } printf("NULL\n"); } void Destroy(LinkList L) { LinkList p = L, tmp; while (p) { tmp = p; p = p->next; free(tmp); } } ``` ### 执行示例 ``` 输入元素(-1结束): 2 4 6 -1 创建结果: 2 → 4 → 6 → NULL ``` ### 性能优化建议 虽然无需尾指针的方案实现简单,但效率较低。如果需要频繁插入操作,可以考虑: 1. **缓存尾指针**:在链表结构体中添加尾指针成员 ```c typedef struct { LinkList head; LinkList tail; // 添加尾指针缓存 } LinkedList; ``` 2. **双向链表**:使每个节点同时保存前驱和后继指针 ```c typedef struct DNode { ElemType data; struct DNode *prev, *next; } DNode, *DLinkList; ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值