1、创建并操作循环链表
【问题描述】输入n个整数,创建一个双向循环链表进行存储。这些整数从第二个开始,递增有序(设a2<a3<...<an) (ai为第i个整数)。试编写程序,创建双向循环链表,依次将输入的整数存储在该链表的各节点中。然后,将第一个结点删除并插入链表中的适当位置,使整个链表递增有序。
【输入形式】先输入整数的个数,再输入整数列。
【输出形式】以整数递增的顺序,依次输出双向循环链表各个节点存储的整数。
【样例输入】5 3 1 2 4 5
【样例输出】1 2 3 4 5
#include<iostream>
using namespace std;
//定义双向循环链表结构体类型
typedef struct DuLNode {
int data;
struct DuLNode* prior;
struct DuLNode* next;
}DuLNode, * DuLinkList;
//尾插法创建循环双链表
void CreateList(DuLinkList& L) {
L = (DuLinkList)malloc(sizeof(DuLNode));
L->next = L;
L->prior = L;
int n;
cin >> n;
DuLNode* q = L;//设置一个哨兵
for (int i = 0; i < n; i++) {
DuLNode* p = new DuLNode;//生成新节点
cin >> p->data;
q->next = p;
p->prior = q;
p->next=L;
L->prior=p;
q = q->next;
}
}
//删除链表中第一个节点并插入合适的位置
void Sort(DuLinkList& L) {
DuLNode* p = L->next;//p为首节点
DuLNode* elem = p->next; //遍历剩余节点,确定插入位置
while (p->data > elem->data && elem!=L ) {//elem永远指向插入位置的后一个位置,共有三种情况:
elem = elem->next; //1.插入位置在链表开头
} //2.插入位置在中间
//删除首节点p //3.插入位置在链表末尾
p->next->prior = p->prior;
p->prior->next = p->next;
//将p插入适当位置
p->prior = elem->prior;
p->next = elem->prior->next;
elem->prior->next = p;
elem->prior = p;
}
//链表的输出
void Output(DuLinkList& L) {
DuLNode* p = L->next;
while (p != L) {
cout << p->data << " ";
p = p->next;
}
}
int main() {
DuLinkList L;
CreateList(L);
Sort(L);
Output(L);
return 0;
}
2、创建链表
【问题描述】定义一个包含学生某门课程成绩信息(学号、成绩)的单链表,读入相应的成绩数据来完成学生成绩信息表的创建。然后,逐行输出每个学生的成绩信息。
【输入形式】输入1行,包括3位同学的成绩信息(学号、成绩)。学号、成绩之间用半角逗号“,”分隔,相邻同学的成绩信息用空格分隔。其中学号取最后三位,成绩为整数类型。
【输出形式】总计输出3行,每个学生成绩信息占一行,学号、成绩用半角逗号“,”分隔,其中学号取后三位。
【样例输入】201,98 202,94 203,89
【样例输出】
[num=201,score=98]
[num=202,score=94]
[num=203,score=89]
# include<iostream>
using namespace std;
typedef struct StuInfo {
struct StuInfo* next;
int num;//学号
int score;//成绩
}StuInfo, * StuInfoList;
//尾插法创建单链表
void Creat_List(StuInfoList& L) {
L = (StuInfoList)malloc(sizeof(StuInfo));//建立带头结点的单链表
L->next = NULL;
StuInfo* q = L;//设一个哨兵
char c;//处理逗号
for (int i = 0; i < 3; i++) {
StuInfo* p = new StuInfo;//生成新节点
cin >> p->num;
getchar();
cin >> p->score;
q->next = p;
q = p;
}
}
void Output(StuInfoList& L) {
StuInfo* p = L->next;
for (int i = 0; i < 3; i++) {
int num = p->num;
if (num >= 0 && num < 10) { //学号后三位为一位数
cout << "[num=00" << p->num << ",score=" << p->score << "]" << endl;
}
else if (num >= 10 && num < 100) {//学号为两位数
cout << "[num=0" << p->num << ",score=" << p->score << "]" << endl;
}
else
cout << "[num=" << p->num << ",score=" << p->score << "]" << endl;
p = p->next;
}
}
int main() {
StuInfoList L;
Creat_List(L);
Output(L);
return 0;
}
3、数组主元素
【问题描述】已知一个整数序列A长度为N其中若存在a且a的个数大于N/2则称为A的主元素。例如:0 5 5 3 5 7 5 5 ,则为主元素 5。又如:0 5 5 3 5 1 5 7,则其中没有主元素。假设中的个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出的主元素。若存在主元素则输出该元素否则输出-1
【输入形式】一个整数数组
【输出形式】主元素
[方法一]:双层循环遍历数组,找到主元素(节省了空间,时间复杂度为n^2)
[方法二]:设置一个计数数组count[maxnum],每出现一个数字num,count[num](当maxnum很大时,非常浪费空间)
这里采用第一种方法
# include<iostream>
using namespace std;
typedef struct {
int* elem;
int length;
}SqList;
int main() {
SqList L;
L.elem = new int[100];
L.length = 0;
int num = 0;
int maxnum = 0;
char ch = ' ';
while (cin >> num) { //读入数据
L.elem[L.length] = num;
L.length++;
if (ch = getchar() == '\n')//读到回车,停止读入
break;
}
for (int i = 0; i < L.length / 2 + 1; i++) {//对表中前半段元素依次查找
int count = 0;
for (int j = i; j < L.length; j++) {
if (L.elem[i] == L.elem[j])
count++;
}
if (count > L.length / 2) {
maxnum = L.elem[i];//记录count取最大值时对应的元素
break;
}
maxnum = -1;//未找到,将maxnum赋值为一
}
cout << maxnum << endl;//输出结果
return 0;
}
4、合并链表
【问题描述】
两个非降序链表的并集,例如将链表1->2->3 和 2->3->5 并为 1->2->3->5,只能输出结果,不能修改两个链表的数据。
【输入形式】
第一行为第一个链表的各结点值,以空格分隔。
第二行为第二个链表的各结点值,以空格分隔。
【输出形式】
合并好的链表,以非降序排列,值与值之间以空格分隔
⚠注意题目中要求不能修改原链表,因此需要新建一个单链表,每次建立需要建立新节点,并将原链表中的值赋给新节点
# include<iostream>
using namespace std;
typedef struct LNode {
struct LNode* next;
int data;
int length;
}LNode, * LinkList;
//尾插法创建单链表
void Creat_List(LinkList& L) {
L = new LNode;
L->length = 0;
LNode* q = L;
LNode* p = new LNode;
p->next = NULL;
cin >> p->data;
q->next = p;
q = p;
while (cin.get() != '\n') { //按下回车时循环停止
LNode* np = new LNode;
np->next = NULL;
cin >> np->data;
q->next = np;
q = np;
}
q->next = NULL;
}
//Merge算法合并链表
void MergeList(LinkList L1, LinkList L2, LinkList& L3) {
L3 = new LNode; L3->next = NULL;
LNode* p1 = L1->next; LNode* p2 = L2->next; LNode* p3 = L3;
while (p1 != NULL && p2 != NULL) {
LNode* newnode = new LNode;
if (p1->data <= p2->data) {
newnode->data = p1->data; p1 = p1->next;
}
else {
newnode->data=p2->data; p2 = p2->next;
}
p3->next = newnode;
p3 = newnode;
}
while (p1 != NULL) {
LNode* newnode = new LNode;
newnode->data = p1->data;
p3->next = newnode; p3 = newnode; p1 = p1->next;
}
while (p2 != NULL) {
LNode* newnode = new LNode;
newnode->data = p2->data;
p3->next = newnode; p3 = newnode; p2 = p2->next;
}
p3->next = NULL;
}
//删除链表中重复元素
void Delete_Node(LinkList& L) {
int max = -10000;
LNode *p = L;
LNode *q = L->next;
while (q!=NULL) {
p->next = NULL;
if (q->data > max) {
p->next = q;
p = q;
max = q->data;
}
q = q->next;
}
}
//输出链表
void Output(LinkList L) {
LNode* elem = L->next;
while (elem != NULL) {
cout << elem->data << ' ';
elem = elem->next;
}
cout << endl;
}
int main() {
LinkList L1;
LinkList L2;
LinkList L3;
Creat_List(L1);
Creat_List(L2);
MergeList(L1, L2, L3);
Delete_Node(L3);
Output(L3);
return 0;
}
5、输出链表倒数第K个节点值
【问题描述】输入一个单向链表,输出该链表中倒数第k个结点,链表的最后一个结点是倒数第1个节点。
【输入形式】输入第一位为K值,其后接一串以空格分隔的整型值。
【输出形式】输出为倒数第K个结点的值,若无,则输出Not Found
方法一:(投机取巧,不建议这样做)直接用头插法创建单链表,这样倒数第k个节点,即为头插法正数第k个节点
# include<iostream>
using namespace std;
typedef struct LNode {
struct LNode* next;
int data;
int length;
}LNOde,*LinkList;
//头插法创建单链表
LinkList Create_List(LinkList &L) {
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
L->length = 0;
while (cin.get()!='\n') { //按下回车时循环停止
LNode* p = new LNode;
cin >> p->data ;
p->next = L->next;
L->next = p;
L->length++;
}
return L;
}
//输出倒数第k个节点
void Output(LinkList L,int k) {
LNode* p = L;
if (k <= 0 || k > L->length) {
cout << "Not Found" << endl;
}
else {
for (int i = 0; i < k; i++) {
p = p->next;
}
cout << p->data << endl;
}
}
int main() {
LinkList L;
int k;
cin >> k;
L=Create_List(L);
Output(L, k);
return 0;
}
方法二:(最推荐的做法)当用尾插法得到一个正序的链表时
思路:设置双指针,前一个指针p移动k个距离后后一个指针q开始移动,两个指针相隔的距离始终为k当p指针碰到末尾时,q指针正好指向倒数第k个节点
#include<iostream>
using namespace std;
typedef struct LNode {
struct LNode* link;
int data;
}LNode,*LinkList;
//尾插法创建链表
void CreateList(LinkList& L) {
L = new LNode;//创建带有头节点的单链表
LNode* p = L;
char c = ' ';
int num;
while (c != '\n') {
LNode* q = new LNode;
q->link = NULL;
cin >> num;
q->data = num;
p->link=q;
p = p->link;
c = getchar();
}
}
void find(LinkList L) {
int k;
cin >> k;
LNode* p = L;
int count = 0;
while (p&&count<k) {//p指针先走k
count++;
p = p->link;
}
if (!p) {//p为空查找失败
cout << "Not Found" << endl;
return 0;
}
LNode* q = L->link;//q指针与p指针相隔k个单位移动
while (p->link!=NULL) {
p = p->link;
q = q->link;
}
cout << q->data<<endl;
}
int main() {
LinkList L;
CreateList(L);
find(L);
return 0;
}