头文件(针对vs2022做了相应更改便于观看)
#include <stdio.h>
#include <stdbool.h>
#include <iostream>
#include <stdbool.h>
#include <algorithm>
#include <math.h>
#pragma warning(disable:4996)//忽略scanf,printf的检查
#pragma warning(disable:6011)//忽略空指针的赋值警告
using namespace std;
结构体定义
typedef struct LNode {
int data;
struct LNode* Next;
}LNode, * LinkList;
typedef struct DNode {//用于双链表,学习单链表时不必理会
int data;
struct DNode* Next;
struct DNode* prior;//前驱指针
}DNode, * DLinklist;
初始化
bool InitList(LinkList& l)
{
l = (LNode*)malloc(sizeof(LNode));
if (l == NULL)
return false;
l->Next = NULL;
return true;
}
bool InitDlinkList(DLinklist& l)
{
l = (DNode*)malloc(sizeof(DNode));
if (l == NULL)
return false;
l->prior = NULL;
l->Next = NULL;
return true;;
}
插入
bool ListInsert(LinkList& l, int i, int e) {//带头结点的按位序插入,e为插入的元素,i为插入位置
if (i < 1)
return false;
LNode* p;
int j = 0;//位序的计数器
p = l;//从头结点开始
while (p != NULL && j < i - 1)//头节点可看作第0个,找i-1
{
p = p->Next;
j++;
}
if (p == NULL)
return false;//i不合法
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->Next = p->Next;
p->Next = s;//顺序不能颠倒,会导致原先后面链表丢失
return true;
//时间:o(n)
}
bool InserNextDNode(DNode* p, DNode* s)//双链表插入,s插到p后面
{
if (p == NULL || s == NULL)
return false;
s->Next = p->Next;
if(p->Next!=NULL)//p为末节点的处理
p->Next->prior = s;
s->prior = p;
p->Next = s;
return true;
}
bool nohead_ListInsert(LinkList& l, int i, int e) {//不带头结点的按位序插入,e为插入的元素,i为插入位置
if (i < 1)
return false;
if (i == 1)//头结点处特殊处理即可
{
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->Next = l;
l = s;
return true;
}
LNode* p;
int j = 1;//位序的计数器
p = l;//从第一个结点开始
while (p != NULL && j < i - 1)//找i-1
{
p = p->Next;
j++;
}
if (p == NULL)
return false;//i不合法
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->Next = p->Next;
p->Next = s;//顺序不能颠倒,会导致原先后面链表丢失
return true;
//时间:o(n)
}
bool InserNextNode(LNode* p, int e)//指定节点p的后插,e为插入元素
{
if (p == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->data = e;
s->Next = p->Next;
p->Next = s;
return true;
}
bool InserPriorNode(LNode* p, int e)//指定节点p的前插,e为插入元素
{
if (p == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->Next = p->Next;
p->Next = s;
s->data = p->data;
p->data = e; //用新的节点s替代原本的p,把原本的p当作是前插的节点罢了
//时间o(1)
//给了头节点去从头找p的前插的话,时间o(n)
return true;
}
删表
void DestoryList(DLinklist& l)
{
while (l->Next != NULL)
DeleteNextDNode(l);
free(l);
l = NULL;
}
删点
bool ListDelete(LinkList& l, int i, int& e)//按位删除,带头结点,i表示第i个,e表示删除位置的data
{
if (i < 1)
return false;
LNode* p=l;
int j = 0;
while (p != NULL && j < i - 1)
{
p = p->Next;
j++;
}
if (p == NULL)
return false;
if (p->Next == NULL)
return false;
LNode* q = p->Next;
p->Next = q->Next;
e = q->data;
free(q);
return true;
//时间o(n)
}
bool DeleteNode(LNode* p)//指定节点删除
{
if (p == NULL)
return false;
LNode* q = p->Next;
if (q == NULL)
{
cout << "此方法不可行,p已是最后节点,q此时会报错,此时应采用头节点找p前驱的法,o(n)";
return false;
}
p->data = p->Next->data;
p->Next = q->Next;
free(q);
return true;
//仍是用后继节点代替p删除,从而达成删除p的效果,时间o(1)
}
bool DeleteNextDNode(DNode* p)//删除p的后续节点
{
if (p == NULL)
return false;
DNode* q = p->Next;
if (q == NULL)
return false;
p->Next = q->Next;
if (q->Next != NULL)
q->Next->prior = p;
free(q);
return true;
}
查表
LNode *GetElem(LinkList l,int i)//按位查找,与上述代码片段相同,o(n)
{
if (i < 0)
return NULL;
LNode* p=l;
int j = 0;
while (p != NULL && j < i )
{
p = p->Next;
j++;
}
return p;
}
LNode* LocalElem(LinkList l, int e)//按值查找,o(n)
{
LNode* p = l->Next;
while (p != NULL &&p->data!=e)
{
p = p->Next;
}
return p;
}
表长
int Length(LinkList l)//统计链表长
{
int len = 0;
LNode* p = l;
while (p->Next != NULL)
{
p = p->Next;
len++;//时间 o(n)
}
return len;
}
建表(头插,尾插)
//尾插法:1.可以不断调用ListInsert插入最后一位,但双重循环,时间上为o(n^2)
LinkList List_TailInsert(LinkList& L)//课本尾插法
{
int x;
L = (LinkList)malloc(sizeof(LNode));//头
LNode* s, * r = L;
cin >> x;
while (x != 9999)//结束标志
{
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->Next = s;
r = s;
cout << x;
}
r->Next = NULL;
return L;
}
LinkList List_headInsert(LinkList& l)//头插,也就是后插 ,用于逆置
{
LNode* s;
int x;
l = (LinkList)malloc(sizeof(LNode));//头
l->Next = NULL;//此句为了清除脏数据
cin >> x;
while (x != 9999)
{
s = (LNode*)malloc(sizeof(LNode));//逆置链表的思想,建议实操
s->data = x;//逆置链表的思想
s->Next = l->Next;//逆置链表的思想
l->Next = s;//逆置链表的思想
cin >> x;
}
return l;
}
王道题1-14
//页数43 p1-13
bool p1(LinkList head, int e)
{
while (head->Next!= NULL)
{
if (head->Next->data == e)
{
LNode* s = head->Next;
if (s->Next == NULL)
{
free(s);
return true;
}
head->Next = s->Next;
free(s);
continue;
}
head = head->Next;
}
return true;
}
bool p2(LinkList head)
{ int minnum = head->Next->data;
LNode* prior=NULL; LNode* cur=NULL;
while (head->Next != NULL)
{
if (head->Next->data < minnum)
{
minnum =head->Next->data;
prior = head;
cur = head->Next;
}
head = head->Next;
}
if (prior != NULL && cur != NULL)
{
prior->Next = cur->Next;
free(cur);
return true;
}
return false;
}
LinkList p3(LinkList l)
{
LNode* cur = l->Next;
LNode* pn = NULL;
l->Next = NULL;
while (cur!=NULL)
{
pn = cur->Next;
cur->Next = l->Next;
l->Next = cur;
cur = pn;
}
return l;
}
bool p4(LinkList head, int n,int N)
{
while (head->Next != NULL)
{
if (head->Next->data > n && head->Next->data < N)
{
LNode* s = head->Next;
if (s->Next == NULL)
{
free(s);
return true;
}
head->Next = s->Next;
free(s);
continue;
}
head = head->Next;
}
return true;
}
void p6(LinkList temp)//原题a,b的大小为n,故原链表元素必为偶数,此算法也仅是考虑了偶数。王道中是单节点更加简便,但时间复杂度都为o(n)
{
LNode* prior = temp->Next;
LNode* cur = prior->Next;
temp->Next = NULL;
if (prior == NULL || cur == NULL)
return;
LNode*a= (LinkList)malloc(sizeof(LNode));
LNode*b = (LinkList)malloc(sizeof(LNode));
LNode* tail = a;
LNode* head = b;
b->Next = NULL;
while (prior&&cur )
{
tail->Next = prior;//weicha
tail = prior;//weicha
prior = cur->Next;
cur->Next = head->Next;//toucha
head->Next = cur;//toucha
if (!prior) break;
cur = prior->Next;
}
tail->Next = NULL;
print(a);
cout << endl;
print(b);
}
void p7(LinkList temp)//前提为排序列表,记录当前值即可。
{
LNode* prior = temp->Next;
if (!prior)
return;
int num = prior->data;
LNode* cur = prior->Next;
if (cur == NULL)
{
cout << prior->data;
return;
}
while (cur->Next!= NULL)
{
if (cur->data == num)
{
prior->Next = cur->Next;
LNode* tmp = cur;
cur = cur->Next;
free(tmp);
continue;
}
cur = cur->Next;
prior = prior->Next;
num = prior->data;
}
print(temp);
cout << endl;
}
void p8(LinkList a, LinkList b)
{
LNode* p = a->Next;
LNode* q = b->Next;
LNode*c = (LinkList)malloc(sizeof(LNode));
LNode* r = c;
while (p && q)
{
if (p->data < q->data)
{
p = p->Next;
}
else if(p->data > q->data) q = q->Next;
else {
LNode* s = (LinkList)malloc(sizeof(LNode));
s->data = p->data;
r->Next = s;
r = s;
p = p->Next;
q = q->Next;
}
}
r->Next = NULL;
print(c);
cout << endl;
}
LinkList p9(LinkList& a, LinkList& b)
{
LNode* p = a->Next;
LNode* q = b->Next;
LNode* u, * pc = a;
while (p && q)
{
if (p->data == q->data)
{
pc->Next = p;
pc = p;
p = p->Next;
u = q;
q = q->Next;
free(u);
}
else if (p->data < q->data)
{
u = p;p = p->Next;
free(u);
}
else {
u = q;
q = q->Next;
free(u);
}
}
while (p)
{
u = p;
p = p->Next;
free(u);
}
while (q)
{
u = q;
q = q->Next;
free(u);
}
pc->Next = NULL;
free(q);
return a;
}
bool p10(LinkList a, LinkList b)//kmp的雏形,这里偷懒直接暴力了,王道答案也是暴力
{
LNode* p = a->Next;
LNode* q = b->Next;
LNode* prior = p;
while (p && q)
{
if (p->data == q->data)
{
p = p->Next;
q = q->Next;
}
else {
prior = prior->Next;
p = prior;
q = b->Next;
}
if (q==NULL)
return true;
else
return false;
}
}
bool p11(DLinklist l)//从头指针开始一个向左一个向右,相等就继续不等就判假即可,样例就不给出了。
{
DNode* p = l->Next;
DNode* q= l->prior;
while (p != q && q->Next != p)
{
if (p->data == q->data)
{
p = p->Next;
q = q->Next;
}
else
return false;
}
return true;
}
LinkList p12(LinkList& a, LinkList& b)//a,b默认为循环单链表,循环链表的题很少用样例重在思想了。
{//一个选择题的思想,找到两个单循环表的尾巴相连再做一些细节处理
LNode* p, * q;
p = a;
while (p->Next != NULL)
p = p->Next;
q = b;
while (q->Next != NULL)
q = q->Next;
p->Next = b;
q->Next = a;
return a;
}
typedef struct DNode13 {//13题双链表,初始化里记得freq置零,此处不演示初始化也不加样例,读者自行实现即可
int data;
int freq=0;
struct DNode13* Next;
struct DNode13* prior;//前驱指针
}DNode13, * DLinklist13;
DLinklist13 p13(DLinklist13& l, int e)
{
DLinklist13 p = l->Next;
DLinklist13 q;//用来记录找的位置
while (p && p->data != e)
p = p->Next;
if (!p)
{
cout << "ERROR";
exit(-1);
}
else {
p->freq++;
if (p->prior == l || p->prior->freq > p->freq)
return p;//p在首或者p比前面少,都说明现在的位置已经是要求的,直接返回
if (p->Next)p->Next->prior = p->prior;
p->prior->Next = p->Next;
q = p->prior;
while (q != l && q->prior->freq <= p->freq)//q从p的prior位置往前找,要么找到头要么找到第一个比他freq值大的地方,在其后面插入p;
q = q->prior;
p->Next = q->Next;
p->prior = q;
q->Next->prior = p;
q->Next = p;
}
return p;
}
void p14(LinkList l, int k)//转换成循环单链表,找到尾节点后断开,注:l不含头节点
{
LNode* p = l;
int lenth=1;
while (p->Next != NULL)
{
p = p->Next;
lenth++;
}
p->Next = l;
p = l;
for (int i = 1;i < lenth - k;i++)
{
p = p->Next;
}
l = p->Next;
p->Next = NULL;
nohead_print(l);
}
王道题15-20
LinkList p15(LinkList head)//Map映射法,或者答案的双指针法,但是环入口不好找,a=nr-x
{
LinkList fast = head;
LinkList slow = head;
while (fast != NULL && fast->Next != NULL)
{
slow = slow->Next;
fast = fast->Next->Next;
if (slow == fast)
break;
}
if( fast->Next == NULL||fast == NULL )
return NULL;
LinkList ph = head;
LinkList ps = slow;
while (ph != ps)
{
ph = ph->Next;
ps = ps->Next;
}//a=nr-x
return ph;
}
int p16(LinkList head)//注:无头指针的链表
{
LNode* fast = head->Next;
LNode* slow = head;
while (fast->Next != NULL && fast != NULL)
{
slow = slow->Next;
fast = fast->Next->Next;
}
LNode* s = slow->Next;
LNode* tmp;
LNode* newhead = (LinkList)malloc(sizeof(LNode));//我带了头节点,带不带都行
newhead->Next = NULL;
while (s)
{
tmp = s->Next;
s->Next = newhead->Next;
newhead->Next = s;
s = tmp;
}
int max = 0;
LNode* first = head;
LNode* second = newhead->Next;
while (first &&second)
{
if ((first->data + second->data) > max)
max = first->data + second->data;
first = first->Next;
second = second->Next;
}
return max;
}
int p17(LinkList head,int k)
{
LinkList p = head;
LinkList q = head;
int count = 0;
while (p)
{
if (count < k)
{
count++;
p = p->Next;
}
else
{
q = q->Next;
p = p->Next;
}
}
if (count < k)
return 0;
else {
cout << q->data;
return 1;
}
}
LinkList p18(LinkList str1, LinkList str2)//第五题的具体实现,不再详解
{
int m = Length(str1);
int n = Length(str2);
LinkList p, q;
for (p = str1;m > n;m--)
p = p->Next;
for (q = str2;m < n;n--)
q = q->Next;
while (p->Next != NULL && p->Next != q->Next)
{
p = p->Next;
q = q->Next;
}
return p->Next;
}
void p19(LinkList head, int n)
{
LinkList p = head;
LinkList r;
int* q, m;
q = (int*)malloc(sizeof(int) * (n + 1));
for (int i = 0;i < n + 1;i++)
*(q + i) = 0;
while (p->Next != NULL)
{
m = abs(p->Next->data);
if (*(q + m) == 0)
{
*(q + m)=1;
p = p->Next;
}
else
{
r = p->Next;
p->Next = r->Next;
free(r);
}
}
free(q);
}
void p20(LinkList head)
{
LNode* fast = head->Next;
LNode* slow = head;
while (fast->Next != NULL && fast != NULL)
{
slow = slow->Next;
fast = fast->Next->Next;
}
fast = slow->Next;
slow->Next = NULL;
LinkList tmp;
while (fast)
{
tmp = fast->Next;
fast->Next = slow->Next;
slow->Next = fast;
fast = tmp;
}
LinkList s;
LinkList r;
s = head->Next;
fast = slow->Next;
while (fast)
{
r = fast->Next;
fast->Next = s->Next;
s->Next = fast;
s = fast->Next;
fast = r;
}
}
全文(部分样例见最后)
#include <stdio.h>
#include <stdbool.h>
#include <iostream>
#include <stdbool.h>
#include <algorithm>
#include <math.h>
#pragma warning(disable:4996)//忽略scanf,printf的检查
#pragma warning(disable:6011)//忽略空指针的赋值警告
#pragma warning(disable:6001)
#define MaxSize 10
#define List_Lenth 100
using namespace std;
typedef struct LNode {//单链表
int data;
struct LNode* Next;
}LNode, * LinkList;
typedef struct DNode {//用于双链表,学习单链表时不必理会
int data;
struct DNode* Next;
struct DNode* prior;//前驱指针
}DNode, * DLinklist;
typedef struct {//静态链表,以数组方式表示链表,next存放下一个数据的数组下标,eg:操作系统的FAT文件分配表
int data;
int next;//以-1作为结束标志
}SLinkList[MaxSize];
bool InitList(LinkList& l)
{
l = (LNode*)malloc(sizeof(LNode));
if (l == NULL)
return false;
l->Next = NULL;
l->data = -1;//头节点默认值,方便区分
//l->Next=l; //代表该单链表为循环单链表,即最后一个节点的next指向头节点,同时检查l-》next==l可确定循环单链表是否为空
return true;
}
bool InitDlinkList(DLinklist& l)
{
l = (DNode*)malloc(sizeof(DNode));
if (l == NULL)
return false;
l->prior = NULL;//l->prior = l ,循环双链表,让头尾节点相连,同时检查l-》next==l可确定循环双链表是否为空
l->Next = NULL;//l->Next = l
return true;;
}
bool ListInsert(LinkList& l, int i, int e) {//带头结点的按位序插入,e为插入的元素,i为插入位置
if (i < 1)
return false;
LNode* p;
int j = 0;//位序的计数器
p = l;//从头结点开始
while (p != NULL && j < i - 1)//头节点可看作第0个,找i-1
{
p = p->Next;
j++;
}
if (p == NULL)
return false;//i不合法
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->Next = p->Next;
p->Next = s;//顺序不能颠倒,会导致原先后面链表丢失
return true;
//时间:o(n)
}
void print(LinkList L)//有头节点的链表打印
{
while (L->Next != NULL)
{
cout << L->Next->data << " ";
L = L->Next;
}
}
void nohead_print(LinkList L)//无头节点的链表打印
{
while (L!= NULL)
{
cout << L->data << " ";
L = L->Next;
}
}
bool InsertNextDNode(DNode* p, DNode* s)//双链表插入,s插到p后面
{
if (p == NULL || s == NULL)
return false;
s->Next = p->Next;
if(p->Next!=NULL)//p为末节点的处理,循环链表则不会出错
p->Next->prior = s;
s->prior = p;
p->Next = s;
return true;
}
bool nohead_ListInsert(LinkList& l, int i, int e) {//不带头结点的按位序插入,e为插入的元素,i为插入位置
if (i < 1)
return false;
if (i == 1)//头结点处特殊处理即可
{
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->Next = l;
l = s;
return true;
}
LNode* p;
int j = 1;//位序的计数器
p = l;//从第一个结点开始
while (p != NULL && j < i - 1)//找i-1
{
p = p->Next;
j++;
}
if (p == NULL)
return false;//i不合法
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->Next = p->Next;
p->Next = s;//顺序不能颠倒,会导致原先后面链表丢失
return true;
//时间:o(n)
}
bool InsertNextNode(LNode* p, int e)//指定节点p的后插,e为插入元素
{
if (p == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->data = e;
s->Next = p->Next;
p->Next = s;
return true;
}
bool InserPriorNode(LNode* p, int e)//指定节点p的前插,e为插入元素
{
if (p == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->Next = p->Next;
p->Next = s;
s->data = p->data;
p->data = e; //用新的节点s替代原本的p,把原本的p当作是前插的节点罢了
//时间o(1)
//给了头节点去从头找p的前插的话,时间o(n)
return true;
}
bool ListDelete(LinkList& l, int i, int& e)//按位删除,带头结点,i表示第i个,e表示删除位置的data
{
if (i < 1)
return false;
LNode* p=l;
int j = 0;
while (p != NULL && j < i - 1)
{
p = p->Next;
j++;
}
if (p == NULL)
return false;
if (p->Next == NULL)
return false;
LNode* q = p->Next;
p->Next = q->Next;
e = q->data;
free(q);
return true;
//时间o(n)
}
bool DeleteNode(LNode* p)//指定节点删除
{
if (p == NULL)
return false;
LNode* q = p->Next;
if (q == NULL)
{
cout << "此方法不可行,p已是最后节点,q此时会报错,此时应采用头节点找p前驱的法,o(n)";
return false;
}
p->data = p->Next->data;
p->Next = q->Next;
free(q);
return true;
//仍是用后继节点代替p删除,从而达成删除p的效果,时间o(1)
}
bool DeleteNextDNode(DNode* p)//删除p的后续节点
{
if (p == NULL)
return false;
DNode* q = p->Next;
if (q == NULL)
return false;
p->Next = q->Next;
if (q->Next != NULL)
q->Next->prior = p;
free(q);
return true;
}
void DestoryList(DLinklist& l)
{
while (l->Next != NULL)
DeleteNextDNode(l);
free(l);
l = NULL;
}
LNode *GetElem(LinkList l,int i)//按位查找,与上述代码片段相同,o(n)
{
if (i < 0)
return NULL;
LNode* p=l;
int j = 0;
while (p != NULL && j < i )
{
p = p->Next;
j++;
}
return p;
}
LNode* LocalElem(LinkList l, int e)//按值查找,o(n)
{
LNode* p = l->Next;
while (p != NULL &&p->data!=e)
{
p = p->Next;
}
return p;
}
int Length(LinkList l)//统计链表长
{
int len = 0;
LNode* p = l;
while (p->Next != NULL)
{
p = p->Next;
len++;//时间 o(n)
}
return len;
}
//尾插法:1.可以不断调用ListInsert插入最后一位,但双重循环,时间上为o(n^2)
LinkList List_TailInsert(LinkList& L)//课本尾插法
{
int x;
L = (LinkList)malloc(sizeof(LNode));//头
LNode* s, * r = L;
cin >> x;
while (x != 9999)//结束标志
{
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->Next = s;
r = s;
cin >> x;
}
r->Next = NULL;
return L;
}
LinkList nohead_List_TailInsert(LinkList& L)//无头尾插法
{
LNode* s, * r=NULL;
int x;
cin >> x;
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->Next = NULL;
if (NULL == L) {
L = s;//将新结点位置首节点也是尾结点
}
else {
r->Next = s;
}
r = s;
cin >> x;
}
r->Next = NULL;
return L;
}
LinkList List_headInsert(LinkList& l)//头插,也就是后插 ,用于逆置
{
LNode* s;
int x;
l = (LinkList)malloc(sizeof(LNode));//头
l->Next = NULL;//此句为了清除脏数据
cin >> x;
while (x != 9999)
{
s = (LNode*)malloc(sizeof(LNode));//逆置链表的思想,建议实操
s->data = x;//逆置链表的思想
s->Next = l->Next;//逆置链表的思想
l->Next = s;//逆置链表的思想
cin >> x;
}
return l;
}
//页数43 p1-13
bool p1(LinkList head, int e)
{
while (head->Next!= NULL)
{
if (head->Next->data == e)
{
LNode* s = head->Next;
if (s->Next == NULL)
{
free(s);
return true;
}
head->Next = s->Next;
free(s);
continue;
}
head = head->Next;
}
return true;
}
bool p2(LinkList head)
{ int minnum = head->Next->data;
LNode* prior=NULL; LNode* cur=NULL;
while (head->Next != NULL)
{
if (head->Next->data < minnum)
{
minnum =head->Next->data;
prior = head;
cur = head->Next;
}
head = head->Next;
}
if (prior != NULL && cur != NULL)
{
prior->Next = cur->Next;
free(cur);
return true;
}
return false;
}
LinkList p3(LinkList l)
{
LNode* cur = l->Next;
LNode* pn = NULL;
l->Next = NULL;
while (cur!=NULL)
{
pn = cur->Next;
cur->Next = l->Next;
l->Next = cur;
cur = pn;
}
return l;
}
bool p4(LinkList head, int n,int N)
{
while (head->Next != NULL)
{
if (head->Next->data > n && head->Next->data < N)
{
LNode* s = head->Next;
if (s->Next == NULL)
{
free(s);
return true;
}
head->Next = s->Next;
free(s);
continue;
}
head = head->Next;
}
return true;
}
void p6(LinkList temp)//原题a,b的大小为n,故原链表元素必为偶数,此算法也仅是考虑了偶数。王道中是单节点更加简便,但时间复杂度都为o(n)
{
LNode* prior = temp->Next;
LNode* cur = prior->Next;
temp->Next = NULL;
if (prior == NULL || cur == NULL)
return;
LNode*a= (LinkList)malloc(sizeof(LNode));
LNode*b = (LinkList)malloc(sizeof(LNode));
LNode* tail = a;
LNode* head = b;
b->Next = NULL;
while (prior&&cur )
{
tail->Next = prior;//weicha
tail = prior;//weicha
prior = cur->Next;
cur->Next = head->Next;//toucha
head->Next = cur;//toucha
if (!prior) break;
cur = prior->Next;
}
tail->Next = NULL;
print(a);
cout << endl;
print(b);
}
void p7(LinkList temp)//前提为排序列表,记录当前值即可。
{
LNode* prior = temp->Next;
if (!prior)
return;
int num = prior->data;
LNode* cur = prior->Next;
if (cur == NULL)
{
cout << prior->data;
return;
}
while (cur->Next!= NULL)
{
if (cur->data == num)
{
prior->Next = cur->Next;
LNode* tmp = cur;
cur = cur->Next;
free(tmp);
continue;
}
cur = cur->Next;
prior = prior->Next;
num = prior->data;
}
print(temp);
cout << endl;
}
void p8(LinkList a, LinkList b)
{
LNode* p = a->Next;
LNode* q = b->Next;
LNode*c = (LinkList)malloc(sizeof(LNode));
LNode* r = c;
while (p && q)
{
if (p->data < q->data)
{
p = p->Next;
}
else if(p->data > q->data) q = q->Next;
else {
LNode* s = (LinkList)malloc(sizeof(LNode));
s->data = p->data;
r->Next = s;
r = s;
p = p->Next;
q = q->Next;
}
}
r->Next = NULL;
print(c);
cout << endl;
}
LinkList p9(LinkList& a, LinkList& b)
{
LNode* p = a->Next;
LNode* q = b->Next;
LNode* u, * pc = a;
while (p && q)
{
if (p->data == q->data)
{
pc->Next = p;
pc = p;
p = p->Next;
u = q;
q = q->Next;
free(u);
}
else if (p->data < q->data)
{
u = p;p = p->Next;
free(u);
}
else {
u = q;
q = q->Next;
free(u);
}
}
while (p)
{
u = p;
p = p->Next;
free(u);
}
while (q)
{
u = q;
q = q->Next;
free(u);
}
pc->Next = NULL;
free(q);
return a;
}
bool p10(LinkList a, LinkList b)//kmp的雏形,这里偷懒直接暴力了,王道答案也是暴力
{
LNode* p = a->Next;
LNode* q = b->Next;
LNode* prior = p;
while (p && q)
{
if (p->data == q->data)
{
p = p->Next;
q = q->Next;
}
else {
prior = prior->Next;
p = prior;
q = b->Next;
}
if (q==NULL)
return true;
else
return false;
}
}
bool p11(DLinklist l)//从头指针开始一个向左一个向右,相等就继续不等就判假即可,样例就不给出了。
{
DNode* p = l->Next;
DNode* q= l->prior;
while (p != q && q->Next != p)
{
if (p->data == q->data)
{
p = p->Next;
q = q->Next;
}
else
return false;
}
return true;
}
LinkList p12(LinkList& a, LinkList& b)//a,b默认为循环单链表,循环链表的题很少用样例重在思想了。
{//一个选择题的思想,找到两个单循环表的尾巴相连再做一些细节处理
LNode* p, * q;
p = a;
while (p->Next != NULL)
p = p->Next;
q = b;
while (q->Next != NULL)
q = q->Next;
p->Next = b;
q->Next = a;
return a;
}
typedef struct DNode13 {//13题双链表,初始化里记得freq置零,此处不演示初始化也不加样例,读者自行实现即可
int data;
int freq=0;
struct DNode13* Next;
struct DNode13* prior;//前驱指针
}DNode13, * DLinklist13;
DLinklist13 p13(DLinklist13& l, int e)
{
DLinklist13 p = l->Next;
DLinklist13 q;//用来记录找的位置
while (p && p->data != e)
p = p->Next;
if (!p)
{
cout << "ERROR";
exit(-1);
}
else {
p->freq++;
if (p->prior == l || p->prior->freq > p->freq)
return p;//p在首或者p比前面少,都说明现在的位置已经是要求的,直接返回
if (p->Next)p->Next->prior = p->prior;
p->prior->Next = p->Next;
q = p->prior;
while (q != l && q->prior->freq <= p->freq)//q从p的prior位置往前找,要么找到头要么找到第一个比他freq值大的地方,在其后面插入p;
q = q->prior;
p->Next = q->Next;
p->prior = q;
q->Next->prior = p;
q->Next = p;
}
return p;
}
void p14(LinkList l, int k)//转换成循环单链表,找到尾节点后断开,注:l不含头节点
{
LNode* p = l;
int lenth=1;
while (p->Next != NULL)
{
p = p->Next;
lenth++;
}
p->Next = l;
p = l;
for (int i = 1;i < lenth - k;i++)
{
p = p->Next;
}
l = p->Next;
p->Next = NULL;
nohead_print(l);
}
LinkList p15(LinkList head)//Map映射法,或者答案的双指针法,但是环入口不好找,a=nr-x
{
LinkList fast = head;
LinkList slow = head;
while (fast != NULL && fast->Next != NULL)
{
slow = slow->Next;
fast = fast->Next->Next;
if (slow == fast)
break;
}
if( fast->Next == NULL||fast == NULL )
return NULL;
LinkList ph = head;
LinkList ps = slow;
while (ph != ps)
{
ph = ph->Next;
ps = ps->Next;
}//a=nr-x
return ph;
}
int p16(LinkList head)//注:无头指针的链表
{
LNode* fast = head->Next;
LNode* slow = head;
while (fast->Next != NULL && fast != NULL)
{
slow = slow->Next;
fast = fast->Next->Next;
}
LNode* s = slow->Next;
LNode* tmp;
LNode* newhead = (LinkList)malloc(sizeof(LNode));//我带了头节点,带不带都行
newhead->Next = NULL;
while (s)
{
tmp = s->Next;
s->Next = newhead->Next;
newhead->Next = s;
s = tmp;
}
int max = 0;
LNode* first = head;
LNode* second = newhead->Next;
while (first &&second)
{
if ((first->data + second->data) > max)
max = first->data + second->data;
first = first->Next;
second = second->Next;
}
return max;
}
int p17(LinkList head,int k)
{
LinkList p = head;
LinkList q = head;
int count = 0;
while (p)
{
if (count < k)
{
count++;
p = p->Next;
}
else
{
q = q->Next;
p = p->Next;
}
}
if (count < k)
return 0;
else {
cout << q->data;
return 1;
}
}
LinkList p18(LinkList str1, LinkList str2)//第五题的具体实现,不再详解
{
int m = Length(str1);
int n = Length(str2);
LinkList p, q;
for (p = str1;m > n;m--)
p = p->Next;
for (q = str2;m < n;n--)
q = q->Next;
while (p->Next != NULL && p->Next != q->Next)
{
p = p->Next;
q = q->Next;
}
return p->Next;
}
void p19(LinkList head, int n)
{
LinkList p = head;
LinkList r;
int* q, m;
q = (int*)malloc(sizeof(int) * (n + 1));
for (int i = 0;i < n + 1;i++)
*(q + i) = 0;
while (p->Next != NULL)
{
m = abs(p->Next->data);
if (*(q + m) == 0)
{
*(q + m)=1;
p = p->Next;
}
else
{
r = p->Next;
p->Next = r->Next;
free(r);
}
}
free(q);
}
void p20(LinkList head)
{
LNode* fast = head->Next;
LNode* slow = head;
while (fast->Next != NULL && fast != NULL)
{
slow = slow->Next;
fast = fast->Next->Next;
}
fast = slow->Next;
slow->Next = NULL;
LinkList tmp;
while (fast)
{
tmp = fast->Next;
fast->Next = slow->Next;
slow->Next = fast;
fast = tmp;
}
LinkList s;
LinkList r;
s = head->Next;
fast = slow->Next;
while (fast)
{
r = fast->Next;
fast->Next = s->Next;
s->Next = fast;
s = fast->Next;
fast = r;
}
}
int main()
{ /* p1
LNode* L;
List_TailInsert(L);
print(L);
cout << endl;
if (p1(L,5))
print(L);*/
//p2
//LNode* L;
//List_TailInsert(L);
//print(L);
//cout << endl;
//if (p2(L))//o(n)
//print(L);
//p3
/* LNode* L;
List_TailInsert(L);
print(L);
cout << endl;
L = p3(L);
print(L);*/
// p4
/* LNode* L;
List_TailInsert(L);
print(L);
cout << endl;
if (p4(L,2,5))
print(L);*/
/* p5
* 找到两个链表的公共节点,找到两个链表的头节点p,q,同时如果有公共节点就意为着这两个链表最后是Y型,最后尾节点处p=q找到
* 那么可以考虑两个链表同步遍历直到满足p=q
*两个链表长度可能不同,分别遍历得到两个长度,len1,len2(假设1》2),算出长度差,长的先遍历(len1-len2),然后同步遍历直到p=q;
*/
//LNode* L;
//List_TailInsert(L);
//print(L);
//cout << endl;
//p6(L);
/* LNode* L;
List_TailInsert(L);
print(L);
cout << endl;
p7(L);*/
//LNode* La;
//LNode* Lb;
//List_TailInsert(La);
//List_TailInsert(Lb);
//print(La);cout << endl;
//print(Lb);cout << endl;
//p8(La, Lb);
//LNode* La;
//LNode* Lb;
//List_TailInsert(La);
//List_TailInsert(Lb);
//print(La);cout << endl;
//print(Lb);cout << endl;
//La=p9(La, Lb);
//print(La);
// LNode* La;
//LNode* Lb;
//List_TailInsert(La);
//List_TailInsert(Lb);
//print(La);cout << endl;
//print(Lb);cout << endl;
//if (p10(La, Lb))
// cout << "是的";
//else cout << "NO";
/* LNode* L = NULL;
int k;
cin >> k;
nohead_List_TailInsert(L);
nohead_print(L);
cout << endl;
p14(L,k);*/
//LNode* L = NULL;
//nohead_List_TailInsert(L);
//nohead_print(L);
//cout << endl;
//cout << p16(L);
}
所用样例
1 2 2 3 4 8 9999 //1
5 9 9 5 4 3 9999 //1
8 9 9 5 5 6 4 2 2 2 1 9999//2
1 2 3 4 5 6 7 8 9999//3
1 2 2 3 4 8 9999 //4
5 9 9 5 4 3 9999 //4
1 2 2 3 4 8 9999 //6
5 9 9 5 4 3 9999 //6
1 2 2 3 4 8 9999 //7
7 10 10 21 30 42 42 42 51 70 9999//7
1 2 3 4 5 6 7 8 9999//8
4 5 6 7 8 9 9999//8
1 2 3 4 5 6 7 8 9999 //9
4 5 6 7 8 9 9999 //9
8 9 9 5 5 6 4 2 2 2 1 9999//10
5 5 6 4 9999 //10
8 9 9 5 5 6 4 2 2 2 1 9999//10
9 5 6 4 9999//10
1
0 1 2 3 9999 //14
8 9 9 5 5 6 4 2 5 2 9999//16 result=14
注:
样例相对简单,有错误恳请各位大佬批评指正!
图中警告可以采取
#pragma warning(disable:28182)
注释掉