3 判断单链表的对称性

3 判断单链表的对称性
作者: 冯向阳时间限制: 1S章节: 课程设计
问题描述 :
设带头结点的单链表的头指针为head,结点结构由data和next两个域构成,其中data域为字符型。在使用单链表ADT的基础上,设计一算法判断该链表的前n个字符是否中心对称。例如 x, xyx,  xyyx都是中心对称。
参考函数原型:
//判断单链表的前n个结点是否中心对称
template<class ElemType>
bool Judge_Symmetry( LinkList<ElemType> &L, int num );
输入说明 :
第一行:顺序表A的数据元素的数据类型标记(0:int,1:double,2:char,3:string)
第二行:待判断对称性的链表长度n
第三行:单链表A的数据元素(数据元素之间以空格分隔)
注意:单链表A中的元素个数可能小于n,也可能大于n。如果元素个数小于n,则判断整个单链表是否对称。
输出说明 :
如第一行输入值为0、1、2、3之外的值,直接输出“err”
否则:
第一行:单链表A的遍历结果(数据元素之间以"->"分隔)
空行
第三行:true(对称)
             false(不对称)

反思:
1.首先稍微复习了一下链表的知识,找到了链表的模板,进行了一些回顾理解
2.分析问题,int函数

* 输入m判断数据类型,输入链表长度n

*构造单链表

*中心对称函数处理

3.判断数据类型还是分成四种情况

int m,n,i=0;
cin>>m>>n;
if(m==0)
{
    LinkList <int> B;
    int input1[100];
    int num;
    while(cin>>input1[i])i++;
    B.CreateList_Tail(i, input1);//回顾链表构造方式
    B.ListTraverse();
    Judge_Symmetry(B,n);
}
其他略

4.Judge_Symmetry函数构造

//判断单链表的前n个结点是否中心对称
* 一个个看是不是对称,i++到中间为止
* 一个i一个n-1看是不是一样
* 如果不一样false,结束循环输出true
template<class ElemType>
bool Judge_Symmetry( LinkList<ElemType> &L, int n )
{
    typename LinkList<ElemType>::Position pa,pb,head;
//这里使用了LinkList<ElemType>::Link,在前面要加“typename”,否则不能编译
    ElemType a,b;
    head=pa=pb=L.GetHead();
    pa=L.NextPos(pa);
    pb=L.NextPos(pb);
    int i,j;
    for(i=1;i<=n/2;i++)
//需要注意的细节就是范围,不过大概想一想就知道了,从1开始不容易出错;n/2和n/2+1是一样的
    {
        pb=L.NextPos(head);
//这个算法很关键的就是每一次pb都得回到一开始再走,这也是链表的缺点所在;当然,可以提前使用一个priorpos函数,不过都一样
        for(j=1;j<=n-i;j++)pb=L.NextPos(pb);
        L.GetElem(pa,a);
        L.GetElem(pb,b);
        if(a!=b)
        {
            cout<<"false";
            return true;//这里不需要break,直接return就行了
        }
        pa=L.NextPos(pa);//别忘了pa在这移动
    }
    cout<<"true";
    return true;
}

5.把用到的函数从模板库中拿出来

遇到的问题
1.无法运行
没办法运行和调试,这时候虽然字很多但也得沉下心来理解是哪里除了问题。聚焦到问题——Gercurelem函数,undefined, 原来是这个函数没有具体申明,所以不能运行。且这个问题没有报错,只是不能运行,所以这是需要积累的无法运行原因。
而没有申明的原因是当时看到它和Getelem函数是一样的,所以就不用它了,没想到没删干净,留了个函数头在模板中
2.选择模板库中模板的时候,发现一次性大量删除就会报错,如果一点点删除则则不会,这个感觉有点奇怪。
完整代码
#include<iostream>//数据流输入/输出:cin>>,cout<<的头文件
#include <algorithm>//算法类函数:sort().....的头文件
#include<string>//字符串操作的头文件
using namespace std;
/* 单链表的结点定义 */
template<class ElemType>
struct Node
{
    ElemType data;
    Node<ElemType> *next;
    Node(Node<ElemType> *ptr = NULL)
    {
        next = ptr; //构造函数1,用于构Node造头结点
    }
    Node(const ElemType &item, Node<ElemType> *ptr = NULL) //构造函数2,用于构造其他结点
//函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
    {
        next = ptr;
        data = item;
    }
};


//带头结点的单链表
template<class ElemType>
class LinkList
{
private:
    Node<ElemType> *head; // 头指针
    Node<ElemType> *tail; // 尾指针
public:
//以下定义两个类型,可以看出,Link和Position类型完全相同,
//只是Link类型被认为指向一个链表,Position类型被认为指向某个位置的结点
    typedef struct Node<ElemType> *Link;
    typedef struct Node<ElemType> *Position;


//create
//无参数的构造函数
    LinkList()
    {
        head = new Node<ElemType>;
        tail=head;
    }
//表尾插入法动态生成链表
    void CreateList_Tail(int n, ElemType A[]);


//基本操作
//遍历链表
    bool ListTraverse() const;


//Get与Set
//获取链表头结点指针
    Link GetHead()
    {
        return head;
    }
//用e返回链表的第i个元素数据
    bool GetElem(int i, ElemType &e);
//用e返回链表pos位置的元素数据
    bool GetElem(Position pos, ElemType &e);
//返回pos位置的后继结点的指针
    Position NextPos(Position pos);
};


//CreateList//
//2.表尾插入动态生成链表
template<class ElemType>
void LinkList<ElemType>::CreateList_Tail(int n, ElemType A[])
{
    Node<ElemType> *r; //r为指向尾结点的指针
    r = head;
    Node<ElemType> *p; //p为指向待插入结点的指针
    for(int i = 0; i < n; i++)
    {
        p = new Node<ElemType>;
        p->data = A[i];
        r->next = p;
        r = p;
    }
    r->next = NULL;
    tail = r;
}


//基本操作//
//ListTraverse,遍历链表
template<class ElemType>
bool LinkList<ElemType>::ListTraverse() const
{
//遍历链表
    Node<ElemType> *p;
    p = head->next;
    while( p->next)
    {
        cout<<p->data<<"->";
        p = p->next;
    } // while
    cout<<p->data<<'\n'<<endl;
    return true;
}


//GetElem and SetElem//
//用e返回第i个元素
template<class ElemType>
bool LinkList<ElemType>::GetElem(int i, ElemType &e)
{
//由于本函数隐含了一个循环,因此会使得程序的时间复杂度增大n倍,因此不建议实现本方法
    Node<ElemType> *p;
    p = head->next;
    int j = 1; //初始化,p指向第一个结点,j为计数器
    while (j < i && p) { //顺链域向后扫描,直到p指向第i个元素或p为空
        p = p->next; //p指向下一个结点
        ++j; //计数器j相应加1
    }
    if (!p || j > i)
        return false; //i值不合法i>n或i<=0
    e = p->data; //取第i个结点的数据域
    return true;
}
//用e返回指针pos所指向结点的值
template<class ElemType>
bool LinkList<ElemType>::GetElem(Position pos, ElemType &e)
{
    Node<ElemType> *p;
    p = head->next;
    while (p && p!=pos) { //顺链域向后扫描,直到p为空或者扫描到q的位置
        p = p->next; //p指向下一个结点
    }
    if (!p)
        return false; //pos不合法
    e = p->data; //取结点的数据域
    return true;
}


//返回pos位置的后继结点的指针
template<class ElemType>
Node<ElemType>* LinkList<ElemType>::NextPos(Position pos)
{
    Node<ElemType> *p;
    p = head;
    while (p && p!=pos) { //顺链域向后扫描,直到p为空或者扫描到q的位置
        p = p->next; //p指向下一个结点
    }
    if (!p)
        return NULL; //pos不合法
    return pos->next;
}


//******************************************//以上是模板自带函数


//判断单链表的前n个结点是否中心对称
/*
* 一个个看是不是对称,i++到中间为止
* 一个i一个n-1看是不是一样
* 如果不一样break false
* 结束循环输出true
*/
template<class ElemType>
bool Judge_Symmetry( LinkList<ElemType> &L, int n )
{
    typename LinkList<ElemType>::Position pa,pb,head;
    ElemType a,b;
    head=pa=pb=L.GetHead();
    pa=L.NextPos(pa);
    pb=L.NextPos(pb);
    int i,j;
    for(i=1;i<=n/2;i++)
    {
        pb=L.NextPos(head);
        for(j=1;j<=n-i;j++)pb=L.NextPos(pb);
        L.GetElem(pa,a);
        L.GetElem(pb,b);
        if(a!=b)
        {
            cout<<"false";
            return true;
        }
        pa=L.NextPos(pa);
    }
    cout<<"true";
    return true;
}
/*
* 输入m判断数据类型,输入链表长度n
*构造单链表
*中心对称函数处理
* 试一下能不能把四个合成一个
*/
int main()
{
    int m,n,i=0;
    cin>>m>>n;
    if(m==0)
    {
        LinkList <int> B;
        int input1[100];
        int num;
        while(cin>>input1[i])i++;
        B.CreateList_Tail(i, input1);
        B.ListTraverse();
        Judge_Symmetry(B,n);
    }
    else if(m==1)
    {
        LinkList <double> B;
        double input1[100];
        double num;
        while(cin>>input1[i])i++;
        B.CreateList_Tail(i, input1);
        B.ListTraverse();
        Judge_Symmetry(B,n);
    }
    else if(m==2)
    {
        LinkList <char> B;
        char input1[100];
        char num;
        while(cin>>input1[i])i++;
        B.CreateList_Tail(i, input1);
        B.ListTraverse();
        Judge_Symmetry(B,n);
    }
    else if(m==3)
    {
        LinkList <string> B;
        string input1[100];
        string num;
        while(cin>>input1[i])i++;
        B.CreateList_Tail(i, input1);
        B.ListTraverse();
        Judge_Symmetry(B,n);
    }
    else cout<<"err";
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值