考研408复习,如发现任何错误,请私聊,不胜感谢
单链表代码已更新完毕。
如下:
#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
#include <iomanip>
#include <cstring>
using namespace std;
typedef struct LNode
{
int data;
LNode *next;
}Lnode, *Linklist;
///逆序建立链表
Linklist CreatepositiveLinklist(Linklist &head, int n)
{
head = new Lnode;
head->next = NULL;
for(int i=0;i<n;++i)
{
Linklist p = new Lnode;
cin>>p->data;
p->next = head->next;
head->next = p;
}
return head;
}
///正序建立链表
Linklist CreateNegativeLinklist(Linklist &head, int n)
{
Linklist tail;
head = new Lnode;
head->next = NULL;
tail = head;
for(int i=0;i<n;++i)
{
Linklist p = new Lnode;
cin>>p->data;
p->next = NULL;
tail->next = p;
tail = p;
}
return head;
}
///打印链表
void print_Linklist(Linklist head)
{
if(head->next == NULL)
{
cout<<"The Linklist is NULL !"<<endl;
return;
}
while(head->next->next)
{
cout<<head->next->data<<" ";
head = head->next;
}
cout<<head->next->data<<endl;
}
///按下标查找结点
Lnode *Find_Lnode_byid(Linklist head, int key)
{
if(key == 0)
return head;
if(key < 1)
return NULL;
int num = 1;
head = head->next;
while(head && num < key)
{
head = head->next;
num++;
}
return head;
}
///在position处插入节点值为key的元素
void Insert_Lnode(Linklist &head, int position, int key)
{
if(position <= 0)
{
cout<<"输入不合法,插入失败!"<<endl;
return;
}
Linklist p = Find_Lnode_byid(head, position-1);
Linklist temp = new Lnode;
temp->data = key;
temp->next = p->next;
p->next = temp;
}
///删除位置为position的节点
void Delete_Lnode(Linklist &head, int position)
{
if(position <= 0)
{
cout<<"The input is ERROR!, delete failed!"<<endl;
return;
}
Linklist p = Find_Lnode_byid(head, position);
Linklist q = p->next;
p->next = q->next;
}
///求链表长度
int Linklist_length(Linklist head)
{
if(head->next == NULL)
return 0;
int num = 0;
while(head->next)
{
num++;
head = head->next;
}
return num;
}
///以下为一些综合应用分析题,具有详细题目描述
///1.设计一个递归算法,删除不带头节点的单链表L中所有值为x的节点。
void The_first_problem(Linklist &head, int key)
{
if(head == NULL)
return;
if(head->data == key)
{
Linklist p = head;
head = head->next;
free(p);
The_first_problem(head, key);
}
else
The_first_problem(head->next, key);
}
///这里做一个理解说明:函数进行递归调用时,只是将head进行next操作,并没有改变被删除节点的前驱结点的next指向,疑似断链操作
///其实不然,这里head为调用该函数的外层head->next,故这里实现了head->next=head-next->next的造作过程。
///2.在带头节点的单链表L中,删除所有值为x的节点,并释放其空间,假设值为x的节点不唯一。
Linklist The_second_problem(Linklist &head, int x)
{
Linklist q = head;
Linklist p = head->next;
while(p)
{
if(p->data == x)
{
q->next = p->next;
free(p);
p=q->next;
}
else
{
p=p->next;
q=q->next;
}
}
return head;
}
///3.设L为带头节点的单链表,编写算法实现从尾到头反向输出每个节点的值
void The_third_problem1(Linklist head)///利用辅助空间解决问题
{
int *temp = new int[Linklist_length(head)];
Linklist p = head->next;
for(int i=0;i<Linklist_length(head); ++i, p=p->next)
{
temp[i] = p->data;
}
for(int i=Linklist_length(head)-1; i>0; --i)
cout<<temp[i]<<" ";
cout<<temp[0]<<endl;
}
void The_third_problem2(Linklist head)///使用递归思想解决问题
{
if(head->next)
The_third_problem2(head->next);
cout<<head->data<<" ";
}
///4.试编写在带头节点的单链表L中删除一个最小值节点的高效算法(假设最小值节点是唯一的)
Linklist The_four_problem(Linklist &head)
{
///保存最小值节点的位置及其前驱位置
Linklist q = head, p=head->next;
Linklist mixn = p, mixnpre = q;
while(p)
{
if(p->data < mixn->data)
{
mixn = p;
mixnpre = q;
}
p = p->next;
q = q->next;
}
mixnpre->next = mixn->next;
free(mixn);
return head;
}
///5.试编写算法将带头结点的单链表就地逆置,所谓就地是指辅助空间复杂度为O(1)
Linklist The_five_problem1(Linklist &head)
{
Linklist p = head->next;
Linklist q = p->next;
head->next = NULL;
while(p)
{
p->next = head->next;
head->next = p;
p = q;
if(q)
q = q->next;
}
return head;
}
Linklist The_five_problem2(Linklist &head)
{
Linklist pre, p=head->next, r=p->next;
p->next = NULL;
while(r)
{
pre = p;
p = r;
r = r->next;
p->next = pre;
}
head->next = p;
return head;
}
///6.有一个带头节点的单链表L,设计一个算法,使其元素递增有序
///愿你阅尽千帆,归来仍是少年
Linklist The_six_problem(Linklist &head)
{
///采用插入排序思想,即构造一个单链表,然后遍历L,每走一个节点,插入一个节点。
Linklist p = head->next, r = p->next;
p->next = NULL;
p = r;
r = r->next;
while(p)
{
Linklist temp = head->next, tempre = head;
while(tempre)
{
if(temp == NULL)
{
tempre->next = p;
p->next = NULL;
break;
}
if(p->data < temp->data)
{
p->next = temp;
tempre->next = p;
break;
}
temp = temp->next;
tempre = tempre->next;
}
if(r)
{
p = r;
r = r->next;
}
else
break;
}
return head;
}
///7.设在一个带表头节点的单链表L中所有元素节点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值之间的元素
///人生一棋局,无法跳脱,终究是棋子。
Linklist The_seven_problem(Linklist &head, int a, int b)
{
Linklist p = head->next;
Linklist q = head;
while(p)
{
if(p->data >= a && p->data <= b)
{
q->next = p->next;
free(p);
p = q->next;
}
else
{
p = p->next;
q = q->next;
}
}
return head;
}
///8.给定两个单链表,编写算法找出两个链表的公共节点
///虚无缥缈者,是否虚幻。
Linklist The_eight_problem(Linklist head1, Linklist head2)
{
///明确公共节点的定义,即如果两个链表拥有公共节点,那么在该节点之后的所有节点都是重合的,即他们最后一个节点必然是重合的。
int len1 = Linklist_length(head1), len2 = Linklist_length(head2);
Linklist longlist, shortlist;
int dist = abs(len1-len2);///两表长之差
if(len1 > len2)
{
longlist = head1->next;
shortlist = head2->next;
}
else
{
longlist = head2->next;
shortlist = head1->next;
}
while(dist--)
{
longlist = longlist->next;
}
while(longlist)
{
if(longlist == shortlist)
return longlist;
longlist = longlist ->next;
shortlist = shortlist ->next;
}
return NULL;
}
///9.给定一个带头节点的单链表,按照递增次序输出单链表中各节点的数据元素,并释放节点所占的存储空间。(不允许使用数组做辅助空间)
///向来历史都是由强者书写
Linklist The_nine_problem(Linklist &head)
{
///嵌套双重循环,遍历一次找到最小值输出并释放节点空间
while(head->next)
{
Linklist p = head->next;
Linklist pre = head;
Linklist mixn = p, mixnpre = pre;
while(p)
{
if(p->data < mixn->data)
{
mixn = p;
mixnpre = pre;
}
else
{
p = p->next;
pre = pre->next;
}
}
cout<<mixn->data<<endl;
mixnpre->next = mixn->next;
free(mixn);
}
return head;
}
///10.将一个带头节点的单链表A分解为两个带头结点的单链表的A和B,是的A表中元素为原表奇数序号的元素,B表中元素为原表偶数序号的元素,且保持其相对顺序不变。
///逆风翻盘,向阳而生
void The_ten_problem(Linklist &head, Linklist &head1, Linklist &head2)
{
Linklist tail2;
head2 = new Lnode;
head2->next = NULL;
tail2 = head2;
Linklist tail1;
head1 = new Lnode;
head1->next = NULL;
tail1 = head1;
Linklist p = head->next;
int len = Linklist_length(head);
for(int i=1;i<=len;i++)
{
if(i%2)
{
tail1->next=p;
tail1 = p;
}
else
{
tail2->next = p;
tail2 = p;
}
p = p->next;
}
tail1->next = NULL;
tail2->next = NULL;
}
///11.设C={a1, b1, a2, b2,......an, bn}为线性表,采用带头节点的单链表存放,设计一个就地算法,使A={a1, a2, ...an},B={bn, ...b2, b1}
///与上题思路相同,只不过B单链表改成尾插法。
///12.在一个递增有序的线性表中,有数值相同的元素存在,存储方式为单链表,设计算法去掉数值相同的元素,是表中不存在相同元素。
Linklist The_twelve_problem(Linklist &head)
{
Linklist p = head->next;
Linklist q = p->next;
while(q)
{
if(p->data==q->data)
{
while(p->data == q->data)
{
if(q->next)
q = q->next;
else
break;
}
if(q->next)
p->next = q;
else
p->next = q->next;
}
p=p->next;
q=q->next;
}
return head;
}
///13.假设有两个按元素值递增次序排列的线性表,均以单链表形式存储,归并为一个按照元素值递减的=次序排列的单链表
///并要求利用原来两个单链表节点存放归并后的单链表
Linklist The_thirteen_problem(Linklist &head1, Linklist &head2)
{
///从小开始比较,采用逆序建链表方法
Linklist p = head1->next;
Linklist q = head2->next;
Linklist r;
head1->next = NULL;
while(p && q)
{
if(p->data < q->data)
{
r = p->next;
p->next = head1->next;
head1->next = p;
p = r;
}
else
{
r = q->next;
q->next = head1->next;
head1->next = q;
q = r;
}
}
if(p)
{
q = p;
}
while(q)
{
r = q->next;
q->next = head1->next;
head1->next = q;
q = r;
}
free(head2);
return head1;
}
///14.设A和B是两个单链表(带头节点), 其中元素递增有序,设计一个算法从A和B中公共元素产生单链表C,要求不破坏A和B的节点
Linklist The_fourteen_problem(Linklist &head1, Linklist &head2)
{
Linklist head = new Lnode;
head->next = NULL;
Linklist p = head1->next;
Linklist q = head2->next;
Linklist r = head;
while(p && q)
{
if(p->data <q->data)
p=p->next;
else if(p->data > q->data)
q = q->next;
else
{
Linklist s;
s = new Lnode;
s->data = p->data;
s->next = NULL;
r->next = s;
r = s;
p=p->next;
q=q->next;
}
}
return head;
}
///15.已知两个链表A和B分别表示两个集合,其元素递增排列。编制函数,求A和B的交集,并存放于A链表之中
Linklist The_fifteen_problem(Linklist &head1, Linklist &head2)
{
///较为简单的归并算法,给出王道算法
Linklist p = head1->next;
Linklist q = head2->next;
Linklist c = head1, u;
while(p && q)
{
if(p->data == q->data)
{
c ->next = p;
c=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);
}
c->next=NULL;
free(head2);
return head1;
}
///16.两个连续子序列,判断b是否为a的连续子序列
bool The_sixteen_problem(Linklist &head1, Linklist &head2)
{
Linklist p = head1->next;
Linklist q = head2->next;
Linklist pre = p;
while(p && q)
{
if(q->data == p->data)
{
q = q->next;
p = p->next;
}
else
{
pre = pre->next;
p = pre;
q = head2->next;
}
}
if(q == NULL)
return true;
return false;
}
///21.单链表,查找链表中倒数第k个位置上的节点,若查找成功,输出数据并返回1,否则只返回0
bool The_twentyone_problem(Linklist head, int k)
{
///算法思想,p,q同时指向第一个元素,p先开始移动,当p移动到第k个元素时,q之后与p同步向后移动
///这样当p移动到最后一个元素时,q移动到倒数第k个元素
Linklist p = head->next;
Linklist q = p;
int num = 1;
while(p)
{
if(num <= k)
{
cout<<"xunhuan "<<p->data<<endl;
p=p->next;
num++;
continue;
}
cout<<"p: "<<p->data<<endl;
p = p->next;
q = q->next;
}
if(num <= k)
return 0;
cout<<q->data<<endl;
return 1;
}
///22.单链表,找出两个链表共同后缀的起始位置。说明时间复杂度。
///与第8题相仿,不予赘述
///23.单链表,删除绝对值相等的节点,仅保留第一次出现的节点。
Linklist The_twentythree_problem(Linklist &head, int n)
{
int *temp = new int[n+1];
Linklist p=head->next, pre = head;
memset(temp, 0, n+1);
while(p)
{
int data = p->data>0?p->data:-p->data;
if(temp[data] == 0)
{
p=p->next;
pre = pre->next;
temp[data] = 1;
}
else
{
pre->next = p->next;
free(p);
p = pre->next;
}
}
return head;
}
int main()
{
ios::sync_with_stdio(false);
Linklist head;
int n;
cin>>n;
head = CreateNegativeLinklist(head, n);
/*
Linklist head1, head2;
int n, m;
cin>>n>>m;
head1 = CreateNegativeLinklist(head1, n);
head2 = CreateNegativeLinklist(head2, m);
print_Linklist(head);
cout<<Find_Lnode_byid(head, 3)->data<<endl;
Insert_Lnode(head, 1, 999);
print_Linklist(head);
cout<<Linklist_length(head)<<endl;
//The_first_problem(head, 5);
//print_Linklist(head);
//cout<<Linklist_length(head)<<endl;
The_second_problem(head, 5);
print_Linklist(head);
cout<<Linklist_length(head)<<endl;
The_third_problem1(head);
The_third_problem2(head->next);
head = The_four_problem(head);
print_Linklist(head);
head = The_five_problem2(head);
print_Linklist(head);
head = The_seven_problem(head, 2, 5);
The_ten_problem(head, head1, head2);
print_Linklist(head1);
print_Linklist(head2);
head = The_twelve_problem(head);
print_Linklist(head);
bool flag = The_sixteen_problem(head1, head2);
cout<<flag<<endl;
bool flag = The_twentyone_problem(head, 3);
cout<<flag<<endl;*/
head = The_twentythree_problem(head, 20);
print_Linklist(head);
return 0;
}