数据结构学习之双链表基本操作

数据结构学习之双链表基本操作

0x1 前言

今天实验课,学习了下双链表的写法,这里记录下。

0x2 正文

题目要求如下:
本实验的双链链表元素的类型为char,完成如下实验要求:

(1)初始化单链表h

(2)采用尾插法依次插入a、b、c、d、e

(3)输出单链表h

(4)输出单链表h的长度

(5)判断单链表h是否为空

(6)输出单链表h的第3个元素

(7)输出元素a的逻辑位置

(8)在第4个元素位置上插入元素f

(9)输出单链表h

(10)删除单链表h的第3个元素

(11)输出单链表h

(12)释放单链表h

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

typedef char Elemtype;

typedef struct DNode
{
    Elemtype data; //存放元素值
    struct DNode * prior; //指向前驱结点
    struct DNode * next; //指向后继结点
}DLinkNode;

// 初始化双链表
void InitList(DLinkNode *&h)
{
    h=(DLinkNode *)malloc(sizeof(DLinkNode));
    h->prior=h->next=NULL; //前后指针域置为空
}

// 尾插法插入
void InsertListR(DLinkNode *&h,Elemtype a[],int n)
{
    DLinkNode *s,*r;
    r=h;
    for(int i=0;i<n;i++)
    {
        s=(DLinkNode *)malloc(sizeof(DLinkNode));
        s->data=a[i];
        r->next=s;
        s->prior=r;
        r=s;
    }
    r->next=NULL;
}

//输出双链表
void DispList(DLinkNode *h)
{
    DLinkNode *p;
    p=h->next;
    while(p!=NULL)
    {
        printf("%c ",p->data);
        p=p->next;
    }
    printf("\n");
}

//输出双链表h的长度
int ListLength(DLinkNode *h)
{
    int n=0;
    DLinkNode *p=h->next;
    while(p!=NULL)
    {
        n++;
        p=p->next;
    }
    return(n);
}

//判断线性表是否为空表
bool ListEmpty(DLinkNode *h)
{
    return(h->next==NULL);
}

//输出指定下标的元素
char LocateElemByIndex(DLinkNode *h,int i)
{
    DLinkNode *p=h;
    while(p->next!=NULL&&i)
    {
        i--;
        p=p->next;
    }
    if(p->next==NULL)
    {
        return(false);
    }
    else
        return(p->data);
}

// 输出指定元素的位置
int LocateElem(DLinkNode *h,Elemtype e)
{
    int n=1;
    DLinkNode *p=h->next;
    while(p!=NULL&&p->data!=e)
    {
        n++;
        p=p->next;
    }
    if(p==NULL)
    {
        return(0);
    }else
        return(n);
}

//在指定位置插入指定的元素
bool ListInsert(DLinkNode *&h,int i,Elemtype e)
{
    DLinkNode *p=h,*s;
    int j=0;
    if(i<=0) return(false);
    while(j<i-1&&p!=NULL)
    {
        j++;
        p=p->next;
    }
    if(p==NULL)
    {
        return false;
    }
    s=(DLinkNode *)malloc(sizeof(DLinkNode));
    s->data=e;
    s->prior=p;
    s->next=p->next;
    if(p->next!=NULL)
        p->next->prior=s;
    p->next=s;
    return(true);
}

//删除指定下标元素
bool ListDelete(DLinkNode *&h,int i,Elemtype &e)
{
    DLinkNode *p=h,*q;
    int j=0;
    if(i<=0) return(false);
    while(j<i-1&&p!=NULL)
    {
        j++;
        p=p->next;
    }
    if(p==NULL)
    {
        return(false);
    }else
    {
        q=p->next;
        if(q==NULL)
            return(false);
        e=q->data;
        p->next=q->next;
        if(p->next!=NULL)
            q->prior=p;
        free(q);
        return(true);
    }
}

//释放循环链表
void DestroyList(DLinkNode *&h)
{
    DLinkNode *pre=h,*p=h->next;
    while(p!=NULL)
    {
        free(pre);
        pre=p;
        p=p->next;
    }
    free(pre);
    cout<< "List has been destroyed!" <<endl;
}
int main()
{
    DLinkNode *h;
    char e;
    InitList(h);
    char a[5]={'a','b','c','d','e'};
    InsertListR(h,a,5);
    DispList(h);
    cout<< ListLength(h) <<endl;
    if(ListEmpty(h))
    {
        cout<< "List is Empty!"<<endl;
    }else
    {
        cout<<"List isn't Empty!"<<endl;
    };
    cout<< LocateElemByIndex(h,3)<<endl;
    cout<< LocateElem(h,'a')<<endl;
    ListInsert(h,4,'f');
    DispList(h);
    ListDelete(h,3,e);
    DispList(h);
    DestroyList(h);
    return 0;
}

运行结果如下图:
《数据结构学习之双链表基本操作》

0x3 总结

感觉和单链表不是很大区别,主要是在插入或者删除的时候注意处理下前继指针,比如判断后继是否存在,然后修改后继的前继指针。

点赞