1、已知单链表L(带头节点)是一个递增有序表,试编写一算法,删除表中值大于min且小于max的节点(若表中有这样的节点),同时释放被删节点的空间,这里min和max是两个给定参数。请分析算法时间复杂度。
#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct LNode{
int a;
LNode *next;
};
LNode *init_List(int n){ //初始化链表
LNode *L;
L=(LNode *)malloc(sizeof(LNode));
L->next=NULL;
LNode *p;
LNode *r = L;
if(n!=0){
int x;
while(n--){
scanf("%d",&x);
p=(LNode *)malloc(sizeof(LNode));
p->a = x;
p->next = NULL;
r->next = p; //使用尾插法
r = p;
}
}
return L;
}
void print_List(LNode *L){ //输出链表内容
LNode *p=L->next;
if(L->next==NULL){
printf("-1\n");
return;
}
while(p->next != NULL){
printf("%d ",p->a); p = p->next;
}
printf("%d\n",p->a);
}
LNode *delete2(LNode *L,int min,int max){ //删除指定区域内的节点
LNode* p=L->next,*q=L,*r;
if(L->next==NULL){
return L;
}
while(p!=NULL){
if(p->a > min && p->a < max){
r=p;
q->next=p->next;
p=q->next;
free(r); //释放被删除节点的空间
}
else{
p=p->next;
q=q->next;
}
}
return L;
}
int main(){
int T,len,q,type,min,max;
LNode * L;
scanf("%d",&T);
while(T--){
scanf("%d",&len);
L=init_List(len);
scanf("%d",&q);
while(q--){
scanf("%d",&type);
if(type==1){
print_List(L);
}
else if(type==2){
scanf("%d%d",&min,&max);
L=delete2(L,min,max);
}
}
}
return 0;
}
2、约瑟夫环问题
1)问题描述:有编号为1, 2…n 的 n 个人按顺时针方向围坐一圈,每人持有一个正整数密码。开始给定一个正整数 m,从第一个人按顺时针方向自1开始报数,报到m者出列,不再参加报数,这时将出列者的密码作为m,从出列者顺时针方向的下一人开始重新自1开始报数。如此下去,直到所有人都出列。试设计算法,输出出列者的序列。
2)实验要求:采用顺序和链式两种存储结构实现
#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct Node{
int m; //m记录密码
int num; //记录初始的位置
Node *next; //下一个节点
};
int count;
Node* init_List(int n){
int num=1;
Node* L,*r,*p;
int m;
L = (Node*)malloc(sizeof(Node));
L->next = NULL;
r=L; //尾插法
if(n==0) return L;
else{
count=0;
while(n--){
p = (Node*)malloc(sizeof(Node));
scanf("%d",&m);
count++; //记录节点数
p->m = m;
p->num = num++;
p->next = NULL;
r->next = p;
r = p;
}
}
r->next = L->next;
return L;
}
void xunhuan_List(Node* L,int m){
Node *p=L->next,*r=L,*q1;
int m1=m;
while(count != 1 ){ //原表中剩一节点则结束
m1-=1; //第一次从本身开始
while(m1--){
r=r->next;
p=p->next;
}
printf("%d ",p->num);
count--;
if(p->m!=0) m1=p->m;
else m1=m;
r->next = p->next; //改变原来的链接关系
p = r->next;
}
printf("%d\n",p->num);
}
int main(){
int a,n,m;
scanf("%d",&a);
while(a--){
Node *L;
scanf("%d",&n);
L = init_List(n);
scanf("%d",&m); //初始密码
xunhuan_List(L,m); //循环
}
return 0;
}
3.一元稀疏多项式简单的计算器
1)问题描述:用线性表表示一元稀疏多项式,设计一个一元多项式运算器。
2)实验要求: 采用单链表存储结构一元稀疏多项式,输入并建立多项式,输出多项式,实现多项式加、减运算。
#include<iostream> //多项式问题
#include<cstdlib>
using namespace std;
typedef struct Node{
int x;
int y;
Node* next;
};
Node* init_List(int n){
Node *L,*p,*r;
int x,y;
L=(Node*)malloc(sizeof(Node));
L->next = NULL;
r=L;
if(n==0){ //使用尾插法
return L;
}
else{
while(n--){
scanf("%d%d",&x,&y);
p=(Node*)malloc(sizeof(Node));
p->x=x;
p->y=y;
p->next = NULL;
r->next = p;
r=p;
}
}
return L;
}
void print_List(Node *L){ //输出链表内容
Node *p=L->next;
if(L->next==NULL){
printf("-1\n");
return;
}
if(p->x>0){
printf("%dX^%d",p->x,p->y);
p=p->next;
}
if(p==NULL){
printf("\n");
return;
}
else{
while(p->next != NULL){
if(p->x>0){
printf("+%dX^%d",p->x,p->y);
p = p->next;
}
else if(p->x<0){
printf("%dX^%d",p->x,p->y);
p = p->next;
}
else if(p->x == 0){
printf("");
p=p->next;
}
}
if(p->x>0){
printf("+%dX^%d\n",p->x,p->y);
}
else if(p->x<0){
printf("%dX^%d\n",p->x,p->y);
}
else if(p->x == 0){
printf("\n");
}
}
}
Node* jian_List(Node* L1,Node* L2){
Node *p1=L1,*p2=L2->next,*r;
int flag;
while(p2!=NULL){
p1=L1->next;
flag=0;
while(p1!=NULL){
if(p1->y==p2->y){
flag=1;
p1->x =p1->x - p2->x;
}
p1=p1->next;
}
if(flag==0 && p1==NULL){
Node* p;
r=L1->next;
while(r->next!=NULL) r=r->next;
p=(Node*)malloc(sizeof(Node));
p->x = -(p2->x);
p->y = p2->y;
p->next = NULL;
r->next = p;
r=p;
}
p2=p2->next;
}
return L1;
}
Node* add_List(Node* L1,Node* L2){
Node *p1=L1,*p2=L2->next,*r;
int flag;
while(p2!=NULL){
p1=L1->next;
flag=0;
while(p1!=NULL){
if(p1->y == p2->y){
flag=1;
p1->x = p1->x + p2->x;
}
p1=p1->next;
}
if(flag==0 && p1==NULL){
Node* p;
r=L1->next;
while(r->next!=NULL) r=r->next;
p=(Node*)malloc(sizeof(Node));
p->x = p2->x;
p->y = p2->y;
p->next = NULL;
r->next = p;
r=p;
}
p2=p2->next;
}
return L1;
}
int main(){
int T,m,n,p,type;
scanf("%d",&T);
while(T--){
Node *L1,*L2,*L21,*L22;
scanf("%d%d",&m,&n);
L1=init_List(m); //初始化多项式1
L2=init_List(n); //初始化多项式2
scanf("%d",&p);
while(p--){
scanf("%d",&type);
if(type==1){
print_List(L1);
print_List(L2);
}
else if(type==2){ //加运算
L1 = add_List(L1,L2);
}
else if(type==3){ //减运算
L1 = jian_List(L1,L2);
}
}
}
return 0;
}
4.十进制数到N进制数的转换
1)问题描述:将从键盘输入的十进制数转换为N(如二进制、八进制、十六进制)进制数据。
2)实验要求: 利用顺序栈实现数制转换问题
3) 实现提示:
- 转换方法利用辗转相除法;
- 所转换的N进制数按低位到高位的顺序产生,而通常的输出是从高位到低位的,恰好与计算过程相反,因此转换过程中每得到一位N进制数则进栈保存,转换完毕后依次出栈则正好是转换结果。
4)注意问题:
- 何时入栈、出栈
算法结束条件
#include<iostream>
using namespace std;
#include<cstdlib>
#include<cstring>
#define Max_Size 100
typedef struct SeqStack {
char data[Max_Size];
int top;
};
SeqStack *initStack() { //初始化栈
SeqStack *s;
s = (SeqStack *)malloc(sizeof(SeqStack));
if (s != NULL)
s->top = -1;
return s;
}
void Push(SeqStack *s, int x) { //入栈
if (s->top == Max_Size) {
return;
}
else {
s->top++;
s->data[s->top] = x;
}
return;
}
int Pop(SeqStack *s) { //出栈
char temp;
if (s->top == -1) {
return 0;
}
else {
temp = s->data[s->top];
s->top--;
}
printf("%c",temp);
}
int main(){
SeqStack *s;
s = initStack(); //2<=n<=36
int x,n;
scanf("%d%d",&x,&n);
int count=0;
if(x == 0){
Push(s,0);
}
int r;
while(x != 0){ //中间利用辗转相除法
r = x % n;
if(r >= 10 && r<=35){ //大于10就转化为相应的字母
Push(s,r+55); //根据ASCALL码转换
}
else{ //小于10就转化为相应数字
Push(s,r+'0');
}
count++;
x /= n;
}
while(s->top != -1) { //循环依次输出栈中的内容
Pop(s);
}
return 0;
}
5.判断“回文”问题
1)问题描述:所谓回文,是指从前向后顺读和从后向前倒读都一样的字符串。
例如,did; pop; I was able 与 elba saw I 等等。
2)实验要求:编写程序,利用栈结构判断一个字符串是否是“回文”。
3)实现提示:
从左向右遇到的字符,若和栈顶元素比较,若不相等,字符入栈,若相等,出栈。如此继续,若栈空,字符串是“回文”,否则不是。
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef struct Node{ //栈
int data[200];
int top;
};
Node *init_List(){ //建立栈
Node *L;
L = (Node*)malloc(sizeof(Node));
L->top=-1;
return L;
}
Node* push(Node* L,char x){ //入栈
L->top++;
L->data[L->top] = x;
return L;
}
Node* pop(Node* L){ //出栈
L->top--;
return L;
}
int main(){
char a[200],b;
int i=0;
Node* L;
L = init_List();
int n=0;
while((b=getchar()) && b!='\n'){
a[i++] = b;
n++;
}
if(n%2==1){
for(i=(n-1)/2;a[i]!='\0';i++){ //中间数字之后的前移
a[i] = a[i+1];
}
n=n-1;
} //end 全部变成偶数个字符
for(i=0;i<n/2;i++){ //前n/2个入栈
L = push(L,a[i]);
}
for(i=n/2;L->top!=-1;i++){ //从第n/2个开始逐个与栈内的元素对比
if(a[i] != L->data[L->top]){
printf("NO");
break;
}
L = pop(L);
}
if(L->top == -1){
printf("YES");
}
return 0;
}