1、查找序列元素(链表)
问题描述
使用带头结点的单链表编程:
一群学生排成一行,输入一个学号,请确定该学号学生所在的位置。
输入说明
第一行输入学生信息:
第一个整数n(0<=n<=100),表示共有n个学生,其后有n个整数,表示n个学生的学号
第二行及以后各行,每行输入一个整数,表示要查找的学生学号。
输出说明
对于每个要查找的学号,输出一个整数,表示要查找学生的位置。如果共有n个学生,则位置序号为1~n。
如果学生不存在,输出“no”,不包括双引号。
每个输出占一行。
输入范例
12 50 51 52 53 54 49 4 5 10 11 9 12
50
11
12
3
输出范例
1
10
12
no
代码
#include<iostream>
using namespace std;
struct student {
int num;
struct student *next;
};
//创建单链表
struct student* create(struct student* head,int n) {
struct student* p, * q;
head = new student;
p = head;
q = head;
for (int i = 0; i < n; i++) {
q = new student;
p->next = q;
p = q;
cin>>q->num;
}
q->next = NULL;
return head;
}
//寻找学号
int find(struct student* head, int num) {
int locate = 0;
while (head) {
if (head->num == num) return locate;
head = head->next;
locate++;
}
return 0;
}
int main() {
student* head = new student;
int n, num;
cin >> n;
head = create(head,n);
int no;
while (cin >> no) {
int res = find(head, no);
if (res == 0) {
cout << "no" << endl;
}
else
cout << res << endl;
}
return 0;
}
2、在链表指定位置插入结点
问题描述
输入若干(不超过100个)非负整数,创建一个不带头结点的单向链表。
再输入一个位置index以及一个数据data,程序中首先创建一个新结点s,s的数据成员为data,然后调用函数insertNode将s插入到链表的指定位置index处,最后输出结果链表。
返回值:
函数返回结果链表的头指针。
输入说明
首先输入若干非负整数,每个整数作为数据放入一个链表结点中,输入-1表示输入结束。
然后输入若干组整数,每组一行,每行包含两个整数,第一个表示需要插入位置index,第二个为新结点的数据。如:输入“1 5”表示在链表的第一个位置(最前面)插入一个结点,结点的数据为5。
输出说明
对于每组输入,输出插入结点之后的结果链表。输出的信息以head开头,以tail结尾,以“-->”分隔。具体见输出范例。
如果输入的index超出了链表的范围(如果链表中已有n个结点,则index的有效范围为 1<= index <= n+1),则不插入,输出原链表。如果是空链表,则直接输出“head-->tail”。
输入范例
1 2 3 -1
1 10
3 20
输出范例
head-->10-->1-->2-->3-->tail
head-->10-->1-->20-->2-->3-->tail
代码
#include <stdio.h>
#include <stdlib.h>
struct student{
int num;
struct student* next;
};
//从键盘读入数据创建链表,新结点插入到尾部
struct student *createByTail(){
struct student *head;
struct student *p1,*p2;
int n;
n=0;
p1=p2=(struct student*)malloc(sizeof(struct student));
scanf("%d",&p1->num);
head=NULL; //首先置链表为空链表
while(p1->num!=-1) //num为-1,意味着用户输入结束
{
n=n+1;
if(n==1) //创建第一个结点
head=p1;
else
p2->next=p1;
p2=p1; //p2始终指向最后一个结点(即尾指针)
p1=(struct student*)malloc(sizeof(struct student)); //p1指向新结点
scanf("%d",&p1->num);
}
p2->next=NULL; //最后一个结点的next赋值为NULL
return head;
}
//输出链表中的信息(num)
void displayLink(struct student* head){
struct student *p;
p=head;
printf("head-->");
while(p!=NULL){
printf("%d-->",p->num);
p=p->next;
}
printf("tail\n");
}
//在链表中第index处插入s指针所指向的结点。index从1开始。
//由于可能插在第一个结点,所以函数返回头指针给主调函数
struct student *insertNode(struct student *head,struct student *s,int index){
struct student *q=head;
int n=1,len=0;
while(q != NULL){
q=q->next;
len++;
}
if(index<1||index>len+1) return head;
q=head;
while(n != index){
q=q->next;
n++;
}
//第一个位置插入结点
if(q == head){
s->next=head;
head=s;
}else{
student *p = head;
while(p->next != q){
p=p->next;
}
s->next=q;
p->next=s;
}
return head;
}
int main(){
struct student *head;
int index,data;
head=createByTail();
while(scanf("%d%d", &index,&data) != -1)
{
struct student * s = (struct student *) malloc(sizeof(struct student));
s->num = data;
head=insertNode(head, s, index);
displayLink(head);
}
return 0;
}
3、删除链表第index个结点
问题描述
输入若干(不超过100个)非负整数,创建一个不带头结点的单向链表。在输入一个位置index,从链表中删除第index个结点,输出结果链表。
输入说明
首先输入若干非负整数,每个整数作为数据放入一个链表结点中,输入-1表示输入结束。
然后输入若干组整数,每组一行,每行仅包含一个整数,表示需要删除的结点的位置index。如:输入1表示删除链表的第一个(最前面一个)结点。
输出说明
对于每组输入,输出删除第index个结点之后的结果链表。输出的信息以head开头,以tail结尾,以“-->”分隔。具体见输出范例。
如果输入的index超出了链表的范围,则不删除,输出原链表。如果是空链表,则直接输出“head-->tail”。
输入范例
1000 2342 8883 -1
4
3
1
1
输出范例
head-->1000-->2342-->8883-->tail
head-->1000-->2342-->tail
head-->2342-->tail
head-->tail
代码
#include <stdio.h>
#include <stdlib.h>
struct student{
int num;
struct student *next;
};
//从键盘读入数据创建链表,新结点插入到尾部
struct student *createByTail(){
struct student *head;
struct student *p1,*p2;
int n;
n=0;
p1=p2=(struct student*)malloc(sizeof(struct student));
scanf("%d",&p1->num);
head=NULL; //首先置链表为空链表
while(p1->num!=-1){ //num为-1.意味着用户输入结束
n=n+1;
if(n==1) head=p1;
else p2->next=p1;
p2=p1;
p1=(struct student*)malloc(sizeof(struct student));
scanf("%d",&p1->num);
}
p2->next=NULL;
return head;
}
//输出链表中的信息(num)
void displayLink(struct student *head){
struct student *p;
p=head;
printf("head-->");
while(p!=NULL){
printf("%d-->",p->num);
p=p->next;
}
printf("tail\n");
}
//删除链表中第index个结点,index从1开始
//由于可能删除第一个结点,所以函数返回头指针给主调函数
struct student *deleteNode(struct student *head,int index){
struct student *q=head;
int n=1,len=0;
while(q != NULL){
q=q->next;
len++;
}
if(index<1||index>len) return head;
q=head;
while(n!=index){
q=q->next;
n++;
}
if(index==1){
head=q->next;
}else{
struct student *p=head;
while(p->next!=q){
p=p->next;
}
p->next=q->next;
}
return head;
}
int main(){
struct student *head;
int index;
head=createByTail();
while(scanf("%d", &index) != -1){
head=deleteNode(head, index);
displayLink(head);
}
}
4、集合的操作
问题描述
输入A、B、C、D四个集合(集合中无重复元素,且元素值都大于0),分别存储在不带头结点的链表中。
本程序先将四个集合执行以下操作:
-
对A、B、C、D分别进行升序排序;
-
做A=A+B操作:先执行两个有序链表A和B的合并,并仍然保持有序,结果存储在A中,然后删除重复元素;
-
做A=A-C操作:将C中出现的元素从A中删除;
-
对D中出现的元素,逐一到A中查询:
-
如果在A中存在,则从A中删除
-
如果在A中不存在,则将元素添加到A中,并保持链表A有序。
-
输出集合A中的元素。
-
输入说明
首先输入一行,包含一个整数N,表示共测试N组数据。
后面接着输入4*N行,每行为一个集合的元素。
每组数据的第1行为集合A的元素,第2行为集合B的元素,第3行为集合C的元素,第4行为集合D的元素。
每个集合的元素值都为大于0的整数,输入时,-1表示结束。
输出说明
输出的信息以head开头,以tail结尾,以“-->”分隔。如果是空链表,则直接输出“head-->tail”。具体见输出范例。
输入范例
2
3 5 8 10 15 9 -1
2 5 8 11 14 -1
2 5 10 -1
3 1 9 -1
3 5 8 10 15 9 -1
2 5 8 11 14 -1
2 5 10 -1
2 3 8 -1
输出范例
head-->1-->8-->11-->14-->15-->tail
head-->2-->9-->11-->14-->15-->tail
代码
#include<stdio.h>
#include<stdlib.h>
struct student{
int num;
struct student *next;
};
//尾接法创建单链表
struct student* createByTail(){
struct student *head;
struct student *p1,*p2;
int n=0;
p1=p2=(struct student*)malloc(sizeof(struct student));
scanf("%d",&p1->num);
head=NULL;
while(p1->num!=-1){
n=n+1;
if(n==1) head=p1;
else p2->next=p1;
p2=p1;
p1=(struct student*)malloc(sizeof(struct student));
scanf("%d",&p1->num);
}
p2->next=NULL;
return head;
}
//输出链表中的信息
void displayLink(struct student *head){
struct student *p;
p=head;
printf("head-->");
while(p!=NULL){
printf("%d-->",p->num);
p=p->next;
}
printf("tail\n");
}
//根据数据域的大小插入,stu指向待插入结点
struct student *insertNodeInOrder(struct student *head,struct student *stu){
struct student *p0,*p1,*p2;
p1=head;
p0=stu;
if(head==NULL){ //目前还是空链表
p0->next=head;
head=p0;
}else{
while((p0->num>p1->num)&&(p1->next!=NULL)){
p2=p1;
p1=p1->next;
}
if(p0->num<=p1->num){
if(head==p1) head=p0;
else p2->next=p0;
p0->next=p1;
}else{
p1->next=p0;
p0->next=NULL;
}
}
return head;
}
struct student *sort(struct student *head){
struct student *p,*s;
p=head;
head=NULL;
while(p){
s=p;
p=p->next;
head=insertNodeInOrder(head,s);
}
return head;
}
struct student * merge(struct student *LA, struct student *LB){
struct student *p,*s;
p=LB;
while(p)
{
s=p;
p=p->next;
LA=insertNodeInOrder(LA, s);
}
return LA;
}
struct student* subtract(struct student* LA, struct student* LB){
struct student *q, * p=LB;
struct student *pre=NULL;//pre指向q的前驱,所以最开始赋为NULL
while(p!=NULL) //对LB链表遍历
{
q=LA;
while (q!=NULL && q->num!=p->num)
{
pre=q;
q=q->next; //在LA中查找是否有元素与p->num相同
}
if (q!=NULL) //找到了相同的元素,则删除q所指向结点
{
if (q==LA) //如果删除第一个结点
{
LA = LA -> next;
free(q);
}
else
{
pre->next=q->next;
free(q);
}
}
p=p->next;
}
return LA;
}
void purge(struct student * head){
struct student *p,*q;
if(head== NULL || head->next == NULL)
return;
p=head;
while(p->next!= NULL){
if(p->num == p->next->num){
q=p->next;
p->next=q->next;
free(q);
}
else{
p=p->next;
}
}
}
struct student* fun(struct student* L1,struct student *L2){
struct student *p1,*p2=L2;
int flag=0; //是否存在相同元素
while(p2!=NULL){ //对L2链表遍历
flag=0;
p1=L1;
while(p1!=NULL){
if(p1->num==p2->num){
flag=1;
break;
}
p1=p1->next;
}
struct student* temp;
temp=p1;
if(flag==1){
struct student* q;
if(temp==L1){
L1=temp->next;
}else{
q=L1;
while(q->next!=temp) q=q->next;
q->next=temp->next;
}
delete temp;
}else{
student *node = new student;
node->num=p2->num;
L1=insertNodeInOrder(L1,node);
}
p2=p2->next;
}
return L1;
}
int main(){
struct student *headA, *headB, *headC, *headD;
int i,n;
while(scanf("%d", &n)!= EOF){
i=0;
while(i<n){
headA=createByTail();//创建链表A
headB=createByTail();//创建链表B
headC=createByTail();//创建链表C
headD=createByTail();//创建链表D
headA = sort(headA);//链表A排序
headB = sort(headB);//链表B排序
headC = sort(headC);//链表C排序
headD = sort(headD);//链表D排序
headA = merge(headA, headB);//将链表B合并到链表A中
purge(headA);//删除链表A中重复元素
headA = subtract(headA, headC);//从链表A中减去链表C中元素
headA=fun(headA, headD);//对链表A和链表D调用fun函数
displayLink(headA);//输出链表A中的元素
i++;
}
}
return 0;
}