双向链表--主要操作

#include<iostream>
template <typename DataType> class DoubleList;
/*对于DoubleList这个类的前向引用声明*/
template <typename DataType> class DoubleListNode {
    //对DoubleListNode这个模板类进行声明
private:
    friend class DoubleList<DataType>;  //将DoubleList这个类声明为自己的友元,
    //然后DoubleList这个双向链表类就可以调用这个DoubleListNode这个类了
    DoubleListNode():m_pprior(NULL), m_pnext(NULL){}
    DoubleListNode(const DataType item, DoubleListNode<DataType>* Prior = NULL, DoubleListNode<DataType>* next = NULL):m_data(item), m_pprior(prior), m_pnext(next) {}
    //DoubleListNode的两个构造函数
    //并且这两个构造函数都被私有化,只有类的成员或者友元才可以访问!
    ~DoubleListNode() {//DoubleListNode的析构函数
        m_pprior = NULL;   //析构函数中使指针指向了NULL
        m_pnext = NULL;
    }
    DataType m_data;   //数据域
    DoubleListNode* m_pprior;//指向前驱结点的指针域
    DoubleListNode* m_pnext;//指向后驱结点的指针域
public:
    DataType getData();  //获取数据的公有成员函数
};
template <typename DataType> DataType DoubleListNode<DataType>::getData() {
    return this->m_data;  //公有成员函数模板getData的类外定义
}
template<typename DataType> class DoubleList {
    //DoubleList双向链表这个模板类的声明
public:
    DoubleList() {
        head = new DoubleListNode<DataType>();
    }
    ~DoubleList() {
        cleanDoubleLink();
        delete head;
    }
public:
    void cleanDoubleList();//清空双向链表
    int getLength();// 获取双向链表的长度
    DoubleListNode<DataType>* findNode(int i = 0);//寻找第i个结点
    DoubleListNode<DataType>* findData(DataType item);//寻找具有给定值数据的结点

    bool insertNode(DataType item, int i = 0);//在第i个结点的后面插入新的结点
    bool removeNode(int i = 0);//删除第i个结点
    DataType getData(int i = 0);//获取第i个结点的数据
private:
    DoubleListNode<DataType>* head;  //头指针
};

template<typename DataType> void DoubleList<DataType>::cleanDoubleLink() {
    DoubleListNode<DataType>* pmove= head->m_pnext, *pdel;
    while(pmove != NULL) {  //一次删除指针后面的结点   pdel是一个临时指针  把链表上每个结点的右指针域都遍历一遍
        pdel = pmove;
        pmove = pdel->m_pnext;
        delete pdel;
    }
    head->m_pnext = NULL;
}

template <typename DataType> int DoubleList<DataType>::getLength() {
    int count = 0;
    DoubleListNode<DataType>* pmove = head->m_pnext;//遍历链表计算结点数
    while(pmove != NULL) {
        pmove = pmove->m_pnext;
        count++;
    }
    return count;
}

template <typename DataType> DoubleListNode<DataType>* DoubleList<DataType>::findNode(int n = 1) {
    if(n < 1) {           //判断位置是否有效0
        cout << "非有效位置" << endl;
        return NULL:
    }
    DoubleListNode<DataType>* pmove = head->m_pnext;
    for(int i = 1; i < n; i++) {   //利用游标指针pmove查找指定位置的结点
        pmove = pmove->m_pnext;
        if(pmove == NULL) {   //判断结点的是否存在
            cout << "不存在指定结点" << endl;
            return NULL;
        }
    }
    return pmove;
}

template<typename DataType> bool DoubleList<DataType>::insertNode(DataType item, int n) {
    int n;
    if(n < 1) {     //判断所插入的位置是否有效
        cout << "插入位置无效" << endl;
        return 0;
    }
    //创建新结点, 设置游标指针
    DoubleListNode<DataType>* newnode = new DoubleListNode<DataType>(item), *pmove = head;
    if(newnode == NULL) {
        cout << "内存分配失败,新结点无法创建!" << endl;
        exit(1);
    }
    for(i = 1; i < n; i++) {
        pmove = pmove->m_pnext;
        if(pmove == NULL && i < n-1) {
            cout << "超出链表长度,插入位置无效" << endl;
            return 0;
        }
    }
    //插入新结点
    newnode-> m_pnext= pmove->m_pnext;
    if(pmove->m_pnext != NULL) {   //判断是否在链表的尾部添加结点
        pmove->m_pnext->m_pprior = newnode;
    }
    newnode->m_pprior = pmove;
    pmove->m_pnext = newnode;
    return 1;
}
template <typename DataType> bool DoubleList<DataType>::removeNode(int n = 1) {
    if(n<1 || n>getlength) {
        cout << "位置不合法" << endl;
        return false;
    }
    DoubleListNode<DataType>* pmove = head->m_pnext, *pdel;
    for(int i = 1; i < n; i++) {
        pmove = pmove->m_pnext;
        if(pmove == NULL) {
            cout << "超出了链表范围" << endl;
            return false;
        }
    }
    //删除结点
    pdel = pmove;
    pmove->m_pprior->m_pnext = pdel->m_pnext;
    pmove->m_pnext->m_pprior = pdel->m_pprior;
    delete pdel;
    return true;
}

template<typename DataType> DataType DoubleList<DataType>::getData(int n = 1) {
    if(n < 1 || n > getlength()) {
        cout << "指定位置无效" << endl;
        exit(1);
    }
    DoubleListNode<DataType>*pmove = head->m_next;
    for(int i = 1; i < n; i++) {
        pmove = pmove->m_next;
        if(pmove == NULL) {
            cout << "指定结点不存在" << endl;
            exit(1);
        }
    }
    if(pmove == NULL) {
        cout << "结点不存在" << endl;
        return NULL;
    }
    return pmove->m_data;
}
template<typename DataType> DoubleListNode<DataType>* DoubleList<DataType>::findData(DataType item) {
    DoubleListNode<DataType>* pmove = head->m_pnext;
    if(pmove == NULL) {
        cout << "链表是空表" << endl;
        exit(1);
    }
    while(pmove->getData() != item) {
        pmove = pmove->m_pnext;
        if(pmove == NULL) {
            cout << "没有所查找的结点" << endl;
            exit(1);
        }
    }
    remove pmove;
}

主函数部分自己写

时间: 2024-11-08 21:24:24

双向链表--主要操作的相关文章

linux内核中对双向链表的操作函数

在linux内核中用的非常多的一种链表是:双向链表.内核中对所用的进程的管理就是通过双向链表来实现的.所以对链表的操作非常的常用也非常的重要,因此内核通过提供一个通用的方法来帮助我们方便的对双链表实现各种操作. struct list_head {struct list_head *next, *prev;} 0,对双向链表中的某个项进行初始化操作的函数: INIT_LIST_HEAD(struct list_head *entry) INIT_LIST_HEAD()的实现方法: static

双向链表的实现与操作(C语言实现)

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.一般我们都构造双向循环链表. 单链表的局限 1,单链表的结点都只有一个指向下一个结点的指针 2,单链表的数据元素无法直接访问其前驱元素 3,逆序访问单链表中的元素是极其耗时的操作 双向链表的操作 双向链表的新操作 1,获取当前游标指向的数据元素 2,将游标重置指向链表中的第一个数据元素 3,将游标移动指向到链表中的下一个数据

3.2 双向链表

1.简介 前面3.1的单链表在操作过程中有一个缺点,就是后面的节点无法直接找到前面的节点,这使很多操作都得从头到尾去搜寻节点,算法效率变得非常低,解决这个问题的方法就是重新定义链表的节点使每个节点有两个指针,一个指向前驱一个指向后驱,这就是双向链表. 节点定义 template<class T> class DLLNode { public: DLLNode() { next = prev = 0; } DLLNode(const T& el, DLLNode<T> *n

数据结构(C实现)------- 双向链表

双向链表中的每一个结点都含有两个指针域,一个指针域存放其后继结点的存储地址,另一个指针域则存放其前驱结点的存储地址. 双向链表结点的类型描述: //双向链表的类型描述 typedef int ElemType; typedef struct node{ ElemType data; struct node *prior,*next; }DuLNode,*DuLinkList; 其中,prior域存放的是其前驱结点的存储地址,next域存放的是其后继结点的存储地址. 双向链表有两个特点:一是可以从

CodeForces 670E(模拟双向链表)

题意:给你一串合法的括号和当前光标的位置和一些操作,问操作完之后的串是怎么样的 思路:模拟一个双向链表的操作,首先先预处理出配对的括号组,然后模拟即可 #include<bits\stdc++.h> using namespace std; const int maxn = 1e6; struct Node { int l,r; }nodes[maxn]; char s1[maxn],s2[maxn]; int a[maxn],d[maxn]; int main() { int n,m,pos

双向链表的java实现

1 package structure; 2 3 import java.util.Arrays; 4 import java.util.Scanner; 5 import static net.mindview.util.Print.*; 6 7 /** 8 * 双向链表的操作 9 * @author Tom Tao 10 * 11 */ 12 class Node { 13 public int value; 14 public Node(int n) { 15 this.value = n

数据结构笔记4双向链表

#include<stdio.h>#include<malloc.h>#include<conio.h>#define OK 1#define ERROR -1#define OVERFLOW -2#define ENDFlAG 0//双向链表节点 struct DNode{ int data; struct DNode *prior,*next;}DNode,*DLinkList;//初始化以及建立,采用尾插法,返回1 int InitLinkList_Asighme

LinkList(双向链表实现)

LinkedList是用链表结构存储数据的,比较适合数据的动态插入和删除,随机访问和遍历速度比较慢,还提供了List接口i中没有定义的方法,专门用于操作表头和表尾的元素,所以可以当作堆栈.队列和双向队列来使用.LInkedList持有头节点和尾节点的引用,有两个构造器,一个是无参构造器,另一个是传入外部集合构造器,它没有像ArrayList一样的初始大小的构造器. 1 //集合元素个数 2 3 transient int size = 0; 4 5 6 7 //头结点引用 8 9 transie

嵌入式系统编程和调试技巧

嵌入式系统的开发,软件的运行稳定可靠是非常重要的.在芯片中,软件是没有质量的,但软件的质量可以决定一颗芯片的成败.芯片设计中,性能能否满足设计要求,除了硬件设计.软硬件配合的设计技巧,对于软件来说,编程的一些技术和技巧同样重要. 本文讲述我在芯片固件开发过程中使用的一些编程调试技巧.针对在嵌入式系统开发中常见的问题,如实时系统下的同步问题,动态内存分配的内存泄漏问题,如何在编程阶段预防BUG出现,调试阶段如何及时发现问题和定位问题.总结下经验,目的是开发一个稳定运行的固件,提高开发效率,提高运行