6.2.2.(2012)
(1)枚举
LNode* ans(LNode *str1, LNode *str2){ LNode *p = str1->next, *q = str2->next; while (p) { q = str2->next; while (q) { if (p == q) return p; q = q->next; } p = p->next; } }
(2)用数组保存每个结点的地址
void ans(LNode *str1, LNode *str2){ LNode *p = str1->next, *q = str2->next; //pq分别指向str1和str2的头结点 LNode A[maxn], B[maxn]; //申明两个分别足够容纳下str1和str2结点数组 int lenA = 0, lenB = 0; while (p) { A[lenA++] = p; p = p->next; } while (q) { B[lenB++] = q; q = q->next; } int i; for (i = 1; i < min(lenA, lenB); i++) { //从后往前找 if (A[lenA - i] != B[lenB - i]) { //第一个不相同的后缀结点 cout << A[lenA - i + 1]; //返回该结点的上一个结点 return; } } cout << A[lenA - i]; //短的链表的元素都是长链表的公共部分 return; }
(3)双指针:较长表的指针移动两表长度的差值,使得两表剩余长度一致,然后一一进行对比
void ans(LNode *str1, LNode *str2){ int len1 = len2 = 0; LNode *p = str1->next, *q = str2->next; while (p) { //分别遍历链表得到长度 len1++; p = p->next; } while (q) { len2++; q = q->next; } if (len1 <= len2) { //移动较长表的指针,并将较短表指针指向其第一个结点 q = str2; for (int i = 0; i < len2 - len1; i++) q = q->next; p = str1->next; } else { p = str1; for (int i = 0; i < len1 - len2; i++) p = p->next; q = str2->next; } int len = min(len1, len2); //len取len1和len2的较小值 for (int i = 0; i < len; i++) { //输出第一个相同结点 if (p == q) { cout << p; return; } p = p->next; q = q->next; } return; }
6.2.3.(2015)
(1)暴力解:每个结点都和剩余所有结点进行一次比较
void ans (LNode *L) { LNode *p = L, *qpre = L, *q = L->link; while (p) { qpre = p; //重置q和qpre结点,q指针指向p的下一个结点,qpre指向q的上一个结点 q = qpre->link; while (q) { if (abs(p->data) == abs(q->data)) { //q和p相等,则删除q结点 qpre->link = q->link; free(q); q = qpre->link; } else { //q和p不相等,q和qpre指针后移 q = q->link; qpre = qpre->link; } } p = p->link; //p指针后移 } return; }
(2) 数组保存出现过的元素
void ans (LNode &L) LNode *p = L->link, *q = L; //p指向头结点,q指向p的上一个结点 bool mark[n + 1] = { false }; while (p) { if (mark[abs(p->data)] == false) { //该值第一次出现 mark[abs(p->data)] = true; //mark中对应下标改为true p = p->link; //pq各自后移 q = q->link; } else { //该值已经在之前的结点中出现过,将该结点删除 q->link = p->link; free(p); p = q->link; } } }
6.2.4.(2019)
(1) 暴力解
void ans(node &L, int n){ node *p = L->next, *q = L; int i; for (i = 0; i < n / 2; i++) { //p指向后半链的第一个结点 p = p->next; q = q->next; } q->next = NULL; //将前后半链分开 node *k = L->next, *kpre = L; //k指向第一个结点,kpre指向k的上一个结点 while (k->next) { k = k->next; pre = pre->next; q = p; while (q->next) q = q->next; //q指向后半链的最后一个结点 q->next = k; //将q插入到kpre后 kpre->next = q; kpre = q; } }
(2)逆置
void ans(node &L) { node *p = L->next, *pre = L, *q = L->next; //q指向前半链第一个结点 for (int i = 0; i < n / 2; i++) { //p指向后半链第一个结点,pre指向前半链最后一个结点 p = p->next; pre = pre->next; } q = pre; //q指向前半链最后一个结点 q->next = NULL; //前后半链分开 while (p) { //采用头插法将后半链逆置 pre = p; p = p->next; pre->next = q->next; q->next = pre; } p = q->next; //p指向后半链第一个结点(逆置后) q = L->next; //q指向第一个结点 pre = L; //pre指向L L->next = NULL; //将L的next指针置空 while (q) { //尾插法循环插入L node* temp = q; //选择前半链的第一个结点插入 q = q->next; pre->next = temp; pre = pre->next; if (p) { //选择后半链的第一个结点插入 temp = p; p = p->next; pre->next = temp; pre = pre->next; } } pre->next = NULL; //将pre的NEXT指针置空 return; }
6.3.树
6.3.1.(2014)
typedef struct BiTNode { struct BiTNode *lchild, *rchild; int weight; }BiTNode; int WPL = 0; //记录整棵树的WPL void PreOrder (BiTNode *T, int d) { //先序遍历 if (T) { //当前结点非空 if (!T->lchild && !T->child) { //叶子结点 WPL = WPL + T->weight * d; //计算当前结点的WPL } PreOrder (T->lchild, d + 1); //进入其左子树 PreOrder (T->rchild, d + 1); //进入其右子树 } } void ans(BiTNode *T) { PreOrder (T, 0); //根节点层高为0 }
6.3.2.(2017)
void ans (BiTNode *T) {