中心对称链表

文章目录

  • 1 题目
  • 2 思路
    • 2.1 思路一
    • 2.2 思路二
    • 2.3 考点
    • 2.4 扩展
  • 3 实现
    • 3.1 思路1
    • 3.2 思路2
    • 3.3 完整例子

1 题目

已知长度为n(n>1)的单链表,表头指针为L,结点结构由data和next两个域构成,其中data域为字符型,设计一个在时间和空间两方面都尽可能高效的算法,判断该单链表是否中心对称(例如xyx,xxyyxx都是中心对称)。

2 思路

2.1 思路一

把单链表的后半段依此存入栈中,然后遍历单链表的前半段,每遍历一个元素,就从栈中弹出一个元素,进行比较,如果值不相等,则该链表为非对称链表,否则,当栈为空时,则该链表为对称链表。

例1: 对于单链表”xyzzyx”,把后半段yxx依次存入栈中,栈中为xyz,依次遍历单链表的前半段xyz,遍历x时,比较栈顶元素x;遍历y时,比较栈顶元素y;遍历z时,比较栈顶元素z,直到栈空,然后该链表为对称链表。

例1: 对于单链表”xyzwqyx”,把后半段yxx依次存入栈中,栈中为xyz,依次遍历单链表的前半段xyz,遍历x时,比较栈顶元素z;遍历y时,比较栈顶元素y;遍历z时,比较栈顶元素q,值不相等,然后该链表为非对称链表。

2.2 思路二

把单链表的后半段原地逆置,然后使用双指针p、q依次遍历单链表的前半段和后半段,若相等,则将p、q指向下一个元素,当q指向空指针时,该链表为对称链表;否则该链表为非对称链表。

2.3 考点

栈、头插法

2.4 扩展

思考:当链表长度未知时,该怎么求?

  • 1,思路一:遍历单链表得到长度,按照原方法。
  • 2,思路二:把单链表依次存入栈和入队列,然后依次出栈和出队列,比较元素。

3 实现

3.1 思路1

int judge1(LinkList L, int n){
    LNode* stack = new LNode[n/2];
    int index = -1;
    LNode *q = L->next, *p = L->next;
    for(int i = 1;i < (n+1)/2 + 1;i++){
        //偶数找对半下一个(4+1)/2+1 = 3
        //奇数找对半下两个 (5+1)/2+ 1 = 4
        q = q->next;
    }
    while(q != nullptr){
        stack[++index] = *q;
        q = q->next;
    }

//打印栈中的数据
//    while(index != -1){
//        printf("%c ",stack[index--].data);
//    }
    
    while(index != -1){
        if(p->data != stack[index--].data)
            return 0;
        p = p->next;    
    }
    return 1;
}

时间复杂度:O(n)
空间复杂度:O(n)

3.2 思路2

int judge2(LinkList L, int n){
    LNode *p = L->next, *q = L->next, *r;
    for(int i = 1;i < (n+1)/2;i++){
        q = q->next;
    }
    p = q->next;
    q->next = nullptr;
    while(p != nullptr){
        r = p->next;
        p->next = q->next;
        q->next = p;
        p = r;
    }
    
    //printLNode(L); //测试打印栈
    p = L->next;
    q = q->next;
    while(q != nullptr){
        if(p->data != q->data){
            return 0;
        }
        p = p->next;
        q = q->next;
    }
    return 1;
    
}

时间复杂度:O(n)
空间复杂度:O(1)

3.3 完整例子

#include

typedef struct LNode{
    char data;
    struct LNode *next;
}LNode,*LinkList;

//尾插法创建链表
LinkList createList(LinkList &L,int n){
    //L = (LinkList)malloc(sizeof(LNode));
    L = new LNode;
    LNode *s, *r= L;
    char x[n + 1];
    scanf("%s", x);
    int index = 0;
    while(n--){
      s = new LNode;
      s->data = x[index++];
      r->next = s;
      r = s;
    }
    r->next = nullptr;
    return L;
}

//打印链表
void printLNode(LNode* L){
    LNode* p = L->next;
    while(p != nullptr){
        printf("%c ", p->data);
        p = p->next;
    }
    printf("\n");
}


int judge1(LinkList L, int n){
    LNode* stack = new LNode[n/2];
    int index = -1;
    LNode *q = L->next, *p = L->next;
    for(int i = 1;i < (n+1)/2 + 1;i++){
        //偶数找对半下一个(4+1)/2+1 = 3
        //奇数找对半下两个 (5+1)/2+ 1 = 4
        q = q->next;
    }
    while(q != nullptr){//栈中存储数据
        stack[++index] = *q;
        q = q->next;
    }

//打印栈中的数据
//    while(index != -1){
//        printf("%c ",stack[index--].data);
//    }
    
    while(index != -1){
        if(p->data != stack[index--].data)
            return 0;
        p = p->next;    
    }
    return 1;
}

int judge2(LinkList L, int n){
    LNode *p = L->next, *q = L->next, *r;
    for(int i = 1;i < (n+1)/2;i++){//遍历到后半段的前一个结点
        q = q->next;
    }
    p = q->next;//存储后半段的头指针的下一个结点(以防断链)
    q->next = nullptr;//(后半段的头指针下一个元素置空)
    while(p != nullptr){//使用头插法原地逆置
        r = p->next;//防止断链
        p->next = q->next;
        q->next = p;
        p = r;
    }
    
    //printLNode(L); //测试打印栈
    p = L->next;
    q = q->next;
    while(q != nullptr){
        if(p->data != q->data){
            return 0;
        }
        p = p->next;
        q = q->next;
    }
    return 1;
    
}


int main(){
    int n;
    scanf("%d", &n);//单链表长度(即字符串长度 )
    LNode* L = new LNode[n];
    createList(L, n);
    printLNode(L);
    if(judge1(L, n) == 1) printf("对称链表");
    else printf("非对称链表");
    delete[] L;
    
    return 0;
}

你可能感兴趣的:(#,链表,链表,数据结构,算法)