数据结构与算法/循环链表与双链表实验

本文展示了如何在单循环链表中删除指定结点的前驱结点,以及如何将不同类型的字符分离到各自的循环链表中。此外,还提供了用于维护按访问频率递减排列的双链表的LOCATE算法实现。

前阵子因为复习期末考试博客好久不更,这阵子把我对数据结构这门课的实验代码贴上来,有对代码感兴趣或者不清楚的地方可以评论,我会一一解答。


1、假设在长度大于 1 的单循环链表中,既无头结点也无头指针。s 为指向某个结点的指针,试编写算法删除结点*s 的直接前驱结点。

2、已知由单链表表示的线性表中,含有三类字符的数据元素(如:字母、数字和其它字符),设计算法构造三个以循环链表示的线性表,使每一个表中只含同一类的字符,且利用原表中的结点空间作为这三个表的空间。(头结点可以另辟空间)

3、有一双链表,每个结点中除有 prior、data 和 next 域外,还有一访问频度域 freq,在链表被启用前,其值均初始化为零。每当在链表上进行一次 LOCATE(L,x)运算,元素值为 x 的结点中 freq 域的值增 1,并使此链表中结点保持按 freq 递减的顺序排列,以便使频繁访问的结点总是靠近表头。设计满足上述要求的 LOCATE算法。


#include <iostream>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define OK 1

//#define ERROR -1

#define OVERFLOW -2

using namespace std;

//结构体

typedef int ElemType;

typedef int Status;

typedef struct LNode

{

    ElemType data;

    struct LNode* next;

}LNode,*LinkList;

typedef struct CNode

{

    char data;

    struct CNode* next;

}CNode,*CLinkList;

typedef struct DulNode

{

    ElemType data;

    struct DulNode* prior;

    struct DulNode* next;

}DulNode,*DuLinkList;

//函数声明:

Status InitList(LinkList &L);//初始化循环链表

Status InsertList(CLinkList &L,char e,int pos);

Status InitList(CLinkList &L);//重载初始化单链表

ElemType GetElem(LinkList &L,int i);//获取表L内第i个元素的值

Status InsertList(LinkList &L,ElemType e,int pos);//向表L中将元素e插入到第pos位

LinkList LocateElem(LinkList &L,ElemType e);//根据想要查找的元素值返回接收结点的地址值

bool isEmpty(LinkList &L);//判断链表是否为空

void ShowAllData(LinkList &L,int length);//显示所有元素

void ShowAllData(CLinkList &L,int length);//重载显示所有元素函数

void DeleteFormerNode(LinkList &L,ElemType e);//删除数据为e的结点的前驱结点

//函数区

int main()

{

    int ListLength = 0,length;//循环链表长度

    ElemType e;

    LinkList SCList;//建立循环链表

    InitList(SCList);//初始化循环链表

    cout<<"请输入循环链表长度:";

    cin>>length;

    if(length<=0)

    {

        cout<<"长度不能小于0,请重试。"<<endl;

        return 0;

    }

    LinkList p=SCList;

    for(int i = 0;i<length;i++)

    {

        LinkList q = new LNode;

        cin>>e;

        if(p->next == p)

        {

            p->data = e;

            p ->next = q;

            q->next = p;

        }

        else InsertList(SCList,e,i);

        ListLength++;

        p = p->next;

    }

    ShowAllData(SCList,ListLength);

    cout<<"请输入你要删除前驱结点的元素的值:";

    int value;

    cin>>value;

    DeleteFormerNode(SCList,value);

    ListLength = length = length - 1;

    ShowAllData(SCList,ListLength);

    //题目2:

    CLinkList CList,A,B,C;

    InitList(CList);

    InitList(A);

    InitList(B);

    InitList(C);

    int CLength;

    cout<<"请输入您要存储的字符个数:";

    cin>>CLength;

    cout<<"请输入您要存储的元素:";

    CLinkList s=CList;

    char* ch;

    //for(int i = 0;i<CLength;i++)

        {

//            CLinkList r = new CNode;

            fflush(stdin);

            scanf("%s",&ch);

            cout<<ch;

        }

    CLinkList pa=A,pb=B,pc=C;

    for(int i = 0;i<CLength;i++)

    {

            if (ch[i]>='a' && ch[i]<='z')

            {

                pa->data = ch[i];

                pa = pa->next;

                continue;

            }

            else if (ch[i]>='0' && ch[i]<='9')

            {

                pb->data = ch[i];

                pb = pb->next;

                continue;

            }

            else

            {

                pc->data = ch[i];

                pc = pc->next;

                continue;

            }

        }

 

        ShowAllData(CList,CLength);

    return 0;

}

void DeleteFormerNode(LinkList &L,ElemType e)//删除数据为e的结点的前驱结点

{

    LinkList p = L,s;

    s = new LNode;

    s->data = e;

    while((s->data) != (p->next->next->data) )

    {

         if(p->next == L)

         {

            cout<<"不存在该元素,删除失败"<<endl;

            return;

         }

         p=p->next;

    }

    s->next = p->next->next->next;

    p->next = s;

 

}

 

void ShowAllData(LinkList &L,int length)//显示所有元素函数

{

    int i = 0;

    LinkList p = L;

    while(i<length)

    {

        cout<<"第"<<i+1<<"个元素为:"<<p->data<<endl;

        p = p->next;

        i++;

    }

    return;

}

void ShowAllData(CLinkList &L,int length)//重载显示所有元素函数

{

    int i = 0;

    CLinkList p = L;

    while(i<length)

    {

        cout<<"第"<<i+1<<"个元素为:"<<p->data<<endl;

        p = p->next;

        i++;

    }

    return;

}

//bool isEmpty(LinkList &L)

//{

//    LinkList p = L;

//    if( ((p->next) == p) && (p->data == NULL) )

//    {

//        cout<<"true";

//         return true;

//    }

//    else

//    {

//        return false;

//    }

//}

 

Status InsertList(LinkList &L,ElemType e,int pos)//向表L中将元素e插入到第pos位

{

    LinkList p = L,q;

    q = new LNode;

    int j = 0;

    while (p && j<pos-1 )

    {

        p = p->next;

        j++;

    }

    q->data = e;

    q->next = p->next;

    p->next = q;

    return OK;

}

Status InsertList(CLinkList &L,char e,int pos)//重写向表L中将元素e插入到第pos位

{

    CLinkList p = L,q;

    q = new CNode;

    int j = 0;

    while (p && j<pos-1 )

    {

        p = p->next;

        j++;

    }

    q->data = e;

    q->next = p->next;

    p->next = q;

    return OK;

}

LinkList LocateElem(LinkList &L,ElemType e)//根据想要查找的元素值返回接收结点的地址值

{

    LinkList p = L->next;

    while(p)

    {

        if( (p->data) == e ) return p;

        else {

            p = p->next;

        }

    }

    return NULL;

}

 

ElemType GetElem(LinkList &L,int pos)//获取表L内第i个元素的值

{

    LinkList p = L->next;

    int j = 0;

    while(p&&j<pos)

    {

        p = p->next;

        j++;

    }

    return p->data;

}

 

Status InitList(LinkList &L)//初始化循环单链表

{

    L = new LNode;

    if(!L)return 0;

    L->next = L;

    return OK;

}

Status InitList(CLinkList &L)//重载初始化单链表

{

    L = new CNode;

    if(!L)exit(0);

    return OK;

}

 

 

//双链表部分:

#include <iostream>

#include <stdio.h>

#include <malloc.h>

using namespace std;

 

typedef struct DNode

{

    int data;

    int freq;

    struct DNode *next;

    struct DNode *prior;

} DinkList;

 

DinkList *h;

void sort(DinkList *&h)//根据freq降序排列,写成一个函数

{

    DinkList *p,*q,*pre;

    p=h->next->next;

    h->next->next=NULL;

    while(p!=NULL)

    {

        q=p->next;

        pre=h;

        while(pre->next!=NULL&&(pre->next->freq)>(p->freq))//根据freq降序

            pre=pre->next;

        p->next=pre->next;

        if(pre->next!=NULL)

            pre->next->prior=p;

        pre->next=p;

        p->prior=pre;

        p=q;

    }

}

 

void LocateNode(DinkList *&h,int x)

{

    DinkList *p;

    p=h->next;

    int i=0;

    //查找x所在的位置

    while(p!=NULL&&p->data!=x)

    {

        p=p->next;

        ++i;

    }

    p->freq++;//x元素的freq++

    //sort(h);//下面是sort

    DinkList *q,*pre;

    p=h->next->next;//把p放在头结点的第二位

    h->next->next=NULL;//把第一位第二位节点断开

    while(p!=NULL)//遍历所有结点为止

    {

        q=p->next;//q在p之后

        pre=h;//pre存储头结点地址

        while(pre->next!=NULL&&pre->next->freq>p->freq)//如果链表没有到表尾并且第一个结点的频度大于第二个结点的频度 进入循环

            pre=pre->next;//pre后挪一位

        p->next=pre->next;//令p下一位链接的是pre的下一位

        if(pre->next!=NULL)

            pre->next->prior=p;

        pre->next=p;

        p->prior=pre;

        p=q;

    }

}

int main()

{

    DinkList *s;

    h=(DinkList *)malloc(sizeof(DinkList));

    int a[6];

    int i;

    for(i=0; i<6; i++)//初始化a数组

        a[i]=i+1;

    h->prior=h->next=NULL;

    for(i=0; i<6; i++)//头插法

    {

        s=(DinkList *)malloc(sizeof(DinkList));

        s->data=a[i];

        s->freq=0;

        s->next=h->next;

        if(h->next!=NULL)

            h->next->prior=s;

        h->next=s;

        s->prior=h;

    }

    DinkList *p;

    int temp;

    while(1)

    {

        printf("请输入要访问的元素");

        scanf("%d",&temp);

        LocateNode(h,temp);

        p=h->next;

        while(p!=NULL)

        {

            cout<<p->data<<" ";

            cout<<"freq="<<p->freq<<endl;

 

            p=p->next;

        }

        cout<<endl;

    }

 

    return 0;

}


顺序存储的线性表 时数 2 性质 验证 内容:1、设线性表存放在向量A[arrsize]的前elenum个分量中,且递增有序。试设计算法,将x插入到线性表的适当位置上,以保持线性表的有序性。 2、用向量作存储结构,试设计算法,仅用个辅助结点,实现将线性表中的结点循环右移k位的运算。 3、用向量作存储结构,试设计算法,仅用个辅助结点,实现将线性表逆置的运算。 要求:了解线性表的逻辑结构特征,熟练掌握线性表的顺序存储结构的描述方法,及在其上实现各种基本运算的方法。 单链表上的操作 时数 2 性质 验证 内容:1、已知带头结点的动态单链表L中的结点是按整数值递增排序的,试写算法将值为x的结点插入到表L中,使L仍然有序。 2、设计算法,逆置带头结点的动态链表L。要求利用原表的结点空间,并要求用尽可能少的时间完成。 3、假设有两个按元素值递增有序的线性表AB,均以单链表作存储结构,试编写算法将A表B表归并成个按元素值递减有序的线性表C,并要求利用原表的空间存放C。 要求:熟练掌握线性表的单链式链接存储结构及在其上实现线性表的各种基本运算的方法。 循环链表双链表 时数 2 性质 验证 内容:1、假设在长度大于1的单循环链表中,既无头结点也无头指针。s为指向某个结点的指针,试编写算法结点*s的直接前驱结点。 2、已知由单链表表示的线性表中,含有三类字符的数据元素(如:字母、数字其它字符),设计算法构造三个以循环链表示的线性表,使每个表中只含同类的字符,且利用原表中的结点空间作为这三个表的空间。(头结点可以另辟空间) 3、有一双链表每个结点priordatanext域外,还有访问频度freq,在链表被启用前,其值均初始化为零。每当在链表上进行次LOCATE(L,x)运算,元素值为x的结点freq的值增1,并使此链表结点保持按freq递减的顺序排列,以便使频繁访问结点总是靠近表头。设计满足上述要求的LOCATE算法。 要求:熟练掌握线性表的循环链式双链式链接存储结构及在其上实现线性表的各种基本运算的方法。 栈队列 时数 2 性质 验证 内容:1、设单链表中存放着n个字符,设计算法,判断该字符串中是否有中心对称关系。例如:xyzzyx、xyzyx都算是中心对称的字符串。 2、设计算法判断个算术表达式的圆括号是否配对。(提示:对表达式进行扫描,遇‘(’进栈,遇‘)’退掉栈顶的‘(’,表达式被扫描完毕,栈为空) 3、假设以带头结点循环链表表示队列,并只设个指针指向队尾,编写相应的置队空、入队出队算法。 要求:掌握栈队列的数据结构的特点;熟练掌握在两种存储结构上实现栈队列的基本运算;学会利用栈队列解决些实际问题。 串运算的实现 时数 2 性质 验证 内容:1、若XY是用结点大小为1的单链表表示的串,设计算法找出X中第个不在Y中出现的字符。 2、设计算法,在顺序串上实现串的比较运算strcmp(S,T)。 3、若ST是用结点大小为1的单链表存储的两个串,设计算法将S中首次T匹配的子串逆置。 要求:熟练掌握串的顺序链接存储结构的实现方法;熟练掌握在两种存储结构上实现串的各种运算。 树的应用 时数 2 性质 验证 内容:1、以二叉链表作存储结构,设计求二叉树高度的算法。 2、棵n个结点的完全二叉树用向量作存储结构,用非递归算法实现对该二叉树进行前序遍历。 3、以二叉链表作存储结构,编写非递归的前序、中序、后序遍历算法。 要求:熟悉二叉树的各种存储结构的特点及适用范围;掌握建立二叉树的存储结构的方法;熟练掌握二叉树的前序、中序、后序遍历的递归及非递归算法;灵活运用递归的遍历算法实现二叉树的其它各种运算。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值