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;
}