文章目录
- 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 = 4q = 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<iostream>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 = 4q = 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;
}