7-8 單向鏈表3 (10 分)
編程實現:輸入一個正整數 repeat (0<repeat<10),做 repeat 次下列運算:
輸入一個正整數 n(0<n<=9)和一組(n個)升序的整數,建立單向鏈表,再輸入一個整數 x,把 x 插入到這組數據中,使該組數據仍然有序。
輸入輸出示例:括號內為說明
輸入樣例:
4 (repeat=4)
5 (數據的個數n=5)
1 2 4 5 7 (5個有序整數)
3 (待插入整數x=3)
4 (數據的個數n=4)
1 2 5 7 (4個有序整數)
-10 (待插入整數x=-10)
3 (數據的個數n=3)
1 2 4 (3個有序整數)
100 (待插入整數x=100)
5 (數據的個數n=5)
1 2 4 5 7 (5個有序整數)
4 (待插入整數x=4)
輸出樣例:
size=6:1 2 3 4 5 7
size=5:-10 1 2 5 7
size=4:1 2 4 100
size=6:1 2 4 4 5 7
#include<iostream>
using namespace std;
struct Node{
int data;
struct Node *next;
};
struct Node *Create(int n)
{
Node *p=NULL,*q=NULL,*head=NULL;
for(int i=0;i<n;i++)
{
q=new Node;//新建一個Node給q
q->next=NULL;//先讓它的next為NULL,比較安全
cin>>q->data;
if(head==NULL)
{
head=p=q;//讓三個指針都先指向第一個Node
}
else
{
p->next=q;//q起到的作用就是把鏈表串起來
p=q;//將p移到鏈表的下一個位置上,以便下一次的串聯
}
}
return head;//返回頭節點
}
struct Node *Insert(Node *head,int x)//插入數x
{
Node *p,*q;
int flag=0;
p=head;
if(head==NULL) return head;
q=new Node;
q->data=x;
q->next=NULL;
if(p->data>x)//如果x的值小於鏈表中的第一個數
{
q->next=p;
head=q;//如果替換了第一個數,記得要修改頭節點
return head;
}
while(p->next!=NULL)
{
if(p->data<=x&&p->next->data>x)
{
q->next=p->next;
p->next=q;
flag=1;
break;
}
p=p->next;//指向下一個,往下一項移動
}
if(flag==0)
p->next=q;
return head;
}
int main()
{
int repeat;
cin>>repeat;
Node *head,*p;
for(int i=0;i<repeat;i++)
{
int n;
cin>>n;
int b;
head=Create(n);
cin>>b;
head=Insert(head,b);
p=head;
cout<<"size="<<n+1<<":";
cout<<p->data;
p=p->next;
while(p!=NULL)
{
cout<<" "<<p->data;
p=p->next;
}
cout<<endl;
}
return 0;
}
7-12 單鏈表基本操作 (5 分)
請編寫程序實現單鏈表插入、刪除結點等基本算法。給定一個單鏈表和一系列插入、刪除結點的操作序列,輸出實施上述操作后的鏈表。單鏈表數據域值為整數。
輸入格式:
輸入第1行為1個正整數n,表示當前單鏈表長度;第2行為n個空格間隔的整數,為該鏈表n個元素的數據域值。第3行為1個正整數m,表示對該鏈表施加的操作數量;接下來m行,每行表示一個操作,為2個或3個整數,格式為0 k d或1 k。0 k d表示在鏈表第k個結點后插入一個數據域值為d的結點,若k=0則表示表頭插入。1 k表示刪除鏈表中第k個結點,此時k不能為0。注:操作序列中若含有不合法的操作(如在長度為5的鏈表中刪除第8個結點、刪除第0個結點等),則忽略該操作。n和m不超過100000。
輸出格式:
輸出為一行整數,表示實施上述m個操作后的鏈表,每個整數后一個空格。輸入數據保證結果鏈表不空。
輸入樣例:
5
1 2 3 4 5
5
0 2 8
0 9 6
0 0 7
1 0
1 6
輸出樣例:
7 1 2 8 3 5
#include<iostream>
using namespace std;
struct Node{
int data;
struct Node *next;
};
struct Node *Create(int n)//創建鏈表
{
Node *p=NULL,*q=NULL,*head=NULL;
for(int i=0;i<n;i++)
{
q=new Node;//新建一個Node給q
q->next=NULL;//先讓它的next為NULL,比較安全
cin>>q->data;
if(head==NULL)
{
head=p=q;//讓三個指針都先指向第一個Node
}
else
{
p->next=q;//q起到的作用就是把鏈表串起來
p=q;//將p移到鏈表的下一個位置上,以便下一次的串聯
}
}
return head;//返回頭節點
}
struct Node *Insert(Node *head,int k,int b)//在鏈表第k個節點后插入一個數值為d的節點
{
Node *p,*q;
p=head;
if(head==NULL) return head;
q=new Node;
q->data=b;
q->next=NULL;
if(k==0)
{
q->next=p;
head=q;
return head;
}
if(k!=0)
{
for(int i=1;i<k;i++)
p=p->next;
q->next=p->next;
p->next=q;
return head;
}
}
struct Node *Delete(Node *head,int k)//刪除某個節點
{
Node *p;
p=head;
if(head==NULL) return head;
if(k==1)
{
p=p->next;
head=p;
return head;
}
else
{
while(k-2)
{
p=p->next;
k--;
}
p->next=p->next->next;
return head;
}
}
int main()
{
int n;
Node *p,*head;
cin>>n;//為單鏈表的長度
head=Create(n);
int m;//為對鏈表的操作數量
cin>>m;
int count=n;
for(int i=0;i<m;i++)
{
int a;
cin>>a;
if(a==0)
{
int k,b;
cin>>k>>b;
if(k>count)
continue;
count++;
head=Insert(head,k,b);
p=head;
}
else if(a==1)
{
int k;
cin>>k;
if(k>count||k==0)
continue;
count--;
head=Delete(head,k);
p=head;
}
}
p=head;
while(p!=NULL)
{
cout<<p->data<<" ";
p=p->next;
}
}
7-13 鏈表操作-插入、查找和刪除 (100 分)
請編寫創建鏈表和輸出鏈表的函數。對於以下數據結點的結構定義,
針對帶頭結點的鏈表,請編程完成以下功能。
struct LNode{
int data; //數據域
struct LNode *next; //指針域
};
struct LNode *head; //頭指針
輸入數據包含若干組命令和數據,一組數據中的第1個字符代表命令,
接下來的是該命令需要的數據。
(1)如果命令是I,功能為創建空鏈表,對應函數:void List_Init(head);
(2)如果命令是A,后跟一個整數data,功能為向鏈表尾部追加一個數據data,
對應函數:void List_Append(head,data);
(3)如果命令是C,后跟一個整數N,再跟N個整數,功能為向鏈表尾部追加N個
數據,可通過調用List_Append()函數實現;
(4)如果命令是P,功能遍歷輸出鏈表中所有數據,數據間用一個空格分隔,對應
函數:void List_print(head),如果鏈表未建立,輸出“List not defined!”,
如果鏈表為空輸出:“List is empty!”。
以上為上一題目的內容,在此基礎上,增加設計如下功能:
(5)如果命令是N,后跟一個整數n和d,功能為向鏈表的第n個位置插入數據d,
可通過調用List_Insert(head,n,d)函數實現;
(6)如果命令是F,后跟一個整數d,功能為在鏈表查找數據d,返回其位序,若
找不到返回-1。可通過調用List_Find(head,d)函數實現;
(7)如果命令是D,后跟一個整數n,功能為刪除鏈表第n個位置的數據,可通過
調用List_Delete(head,n)函數實現。
輸入格式:
若干組命令和數據,很多命令和數據寫在一起請注意識別。
輸出格式:
根據輸入命令輸出相應內容,詳見輸出樣例。
輸入樣例:
I C 5 100 200 300 400 500 P
F 500 N 3 23 N 5 31 P
D 4 P F 99
A 6 P
輸出樣例:
100 200 300 400 500
index:5
100 200 23 300 31 400 500
100 200 23 31 400 500
Not Found!
100 200 23 31 400 500 6
輸入樣例:
I A 100 A 200 A 300 C 4 400 500 600 700 P
F 800 F 500
N 4 4 N 5 5 P
D 2 D 2 D 2 P
D 2 D 2 D 2 P
D 1 D 1 P
D 1 D 1 P
輸出樣例:
100 200 300 400 500 600 700
Not Found!
index:5
100 200 300 4 5 400 500 600 700
100 5 400 500 600 700
100 600 700
700
List is empty!
#include<iostream>
using namespace std;
struct Node{
int data;
struct Node *next;
};
struct Node *head;//在外部聲明,則后面函數中可以直接用void不用struct
void List_Init(Node *&head)//新建一個空鏈表
{
head=new Node;
head->next=NULL;
}
void List_Append(Node *head,int data)//向鏈表的尾部追加一個數據data
{
Node *p,*q;
p=head;
q=new Node;
q->data=data;
q->next=NULL;
while(p->next!=NULL){
p=p->next;
}
p->next=q;
}
void List_print(Node *head)//遍歷輸出鏈表中的所有數據,如果鏈表未建立,輸出"List not defined!"如果鏈表為空輸出:"List is empty!"
{
Node *p;
if(head==NULL){
cout<<"List not defined!"<<endl;
return;
}
if(head->next==NULL){
cout<<"List is empty!"<<endl;
return;
}
p=head->next;//因為這是一個帶頭結點的鏈表,所以head實際上是沒有數的,它指向的才存了第一個數
cout<<p->data;
p=p->next;
while(p!=NULL){
cout<<' '<<p->data;
p=p->next;
}
cout<<endl;
}
void List_Insert(Node *head,int n,int d)//向鏈表的第n個位置插入數據d
{
int i;
Node *p,*q;
q=new Node;
q->data=d;
q->next=NULL;
p=head;
for(i=1;i<n;i++)p=p->next;
q->next=p->next;
p->next=q;
}
int List_Find(Node *head,int d)//在鏈表中查找數據d,並返回其位序,如果找不到則返回-1
{
int cnt=1;
Node *p;
p=head->next;
while(p!=NULL){
if(p->data==d)return cnt;
p=p->next;
cnt++;
}
return -1;
}
void List_Delete(Node *head,int n)//刪除鏈表第n個位置的數據
{
Node *p,*q;
int i;
p=head;
q=p->next;
for(i=1;i<n;i++){
if(p!=NULL)p=p->next;
}
if(p==NULL || p->next==NULL)return;
q=p->next;
p->next=p->next->next;
delete q;
}
int main()
{
head=NULL;
char c;
int i,n,N,data;
while(cin>>c){
if(c=='I')List_Init(head);
if(c=='A'){
cin>>data;
List_Append(head,data);
}
if(c=='C'){
cin>>N;
for(i=0;i<N;i++){
cin>>data;
List_Append(head,data);
}
}
if(c=='P')List_print(head);
if(c=='N'){
cin>>n>>data;
List_Insert(head,n,data);
}
if(c=='F'){
cin>>data;
if(List_Find(head,data)==-1)cout<<"Not Found!"<<endl;
else cout<<"index:"<<List_Find(head,data)<<endl;
}
if(c=='D'){
cin>>n;
List_Delete(head,n);
}
}
return 0;
}
- 若已建立下面的鏈表結構,指針 p、q 分別指向圖中所示結點,則不能將 q 所指結點插入到鏈表末尾的語句是(C )。
A.
q->next = NULL;
p = p->next;
p->next = q;
B.
p = p->next;
q->next = p->next;
p->next = q;
C.
p = p->next;
q->next = p;
p->next = q;
D.
p = (*p).next;
(*q).next = (*p).next;
(*p).next = q;
需要分配較大空間,插入和刪除不需要移動元素的線性表,其存儲結構是(B)。
A.單鏈表
B.靜態鏈表
C.線性鏈表
D.順序存儲結構
-
順序存儲和鏈式存儲沒有優劣之分,根據算法要求靈活使用,但鏈式存儲結構比順序存儲結構能更方便地表示各種邏輯結構
-
對於一個線性表既要求能夠進行較快速地插入和刪除,又要求存儲結構能反映數據之間的邏輯關系,則應該用(鏈式存儲方式 )。
-
‘靜態鏈表需要分配較大的連續空間,插入和刪除不需要移動元素
-
若用單鏈表來表示隊列,則應該選用帶尾指針的循環鏈表
-
刪除最后一個鏈表元素時,就算設置尾指針,也無法刪除最后一個節點,也只能從頭結點往后遍歷,刪除最后一個節點,時間復雜度為O(n)
-
設對n(n>1)個元素的線性表的運算只有4種:刪除第一個元素;刪除最后一個元素;在第一個元素之前插入新元素;
-
在最后一個元素之后插入新元素,則最好使用(只有頭結點指針沒有尾結點指針的循環雙鏈表)。
-
需要分配較大空間,插入和刪除不需要移動元素的線性表,其存儲結構為( 靜態鏈表)。
單鏈表中,增加一個頭結點的目的是(C )
A.使單鏈表至少有一個結點。
B.標識表結點中首結點的位置。
C.方便運算的實現。
D.說明單鏈表是線性表的鏈式存儲
解析:(1) 對帶頭結點的鏈表,在表的任何結點之前插入結點或刪除表中任何結點,所要做的都是修改前一結點的指針域,因為任何元素結點都有前驅結點。若鏈表沒有頭結點,則首元素結點沒有前驅結點,在其前插入結點或刪除該結點時操作會復雜些。 (2) 對帶頭結點的鏈表,表頭指針是指向頭結點的非空指針,因此空表與非空表的處理是一樣的。
2-1
線性表若采用鏈式存儲結構時,要求內存中可用存儲單元的地址 B
A 必須是連續的
B 連續或不連續都可以
C 部分地址必須是連續的
D 一定是不連續的
2-2
線性表L在什么情況下適用於使用鏈式結構實現? A
A 需不斷對L進行刪除插入
B 需經常修改L中的結點值
C L中含有大量的結點
D L中結點結構復雜
2-3
鏈表不具有的特點是: B
A 插入、刪除不需要移動元素
B 方便隨機訪問任一元素
C 不必事先估計存儲空間
D 所需空間與線性長度成正比
2-7
可以用帶表頭附加結點的鏈表表示線性表,也可以用不帶頭結點的鏈表表示線性表,前者最主要的好處是(B)。 (1分)
A 可以加快對表的遍歷
B 使空表和非空表的處理統一
C 節省存儲空間
D 可以提高存取表元素的速度
2-8
在單鏈表中,要刪除某一指定結點,必須先找到該結點的(A)。 (1分)
A 直接前驅
B 自身位置
C 直接后繼
D 直接后繼的后繼
2-9
以下關於鏈式存儲結構的敘述中,(C)是不正確的。 (1分)
A 結點除自身信息外還包括指針域,因此存儲密度小於順序存儲結構
B 邏輯上相鄰的結點物理上不必鄰接
C 可以通過計算直接確定第i個結點的存儲地址
D 插入、刪除運算操作方便,不必移動結點
以下結構類型可用來構造鏈表的是(B)。
A.struct aa{ int a;int * b;};
B.struct bb{ int a;bb * b;};
C.struct cc{ int * a;cc b;};
D.struct dd{ int * a;aa b;};
鏈表要有一個next,next的類型要與結構體的類型一致
2-13
關於delete運算符的下列描述中,(C)是錯誤的。
A.它必須用於new返回的指針;
B.使用它刪除對象時要調用析構函數;
C.對一個指針可以使用多次該運算符;
D.指針名前只有一對方括號符號,不管所刪除數組的維數。
2-14
以下程序中,new語句干了什么。(C)
int** num;
num = new int* [20];
A.分配了長度為20的整數數組空間,並將首元素的指針返回。
B.分配了一個整數變量的空間,並將其初始化為20。
C.分配了長度為20的整數指針數組空間,並將num[0]的指針返回。
D.存在錯誤,編譯不能通過。
關於new運算符的下列描述中,(D)是錯誤的。
A.它可以用來動態創建對象和對象數組;
B.使用它創建的對象或對象數組可以使用運算符delete刪除;
C.使用它創建對象時要調用構造函數;
D.使用它創建對象數組時必須指定初始值
2-11
表達式 “new int”的返回值類型是?
A.int
B.int *
C.int &
D.無法確定
設void f1(int * m,long & n);int a;long b;則以下調用合法的是(B)。
A.f1(a,b);
B.f1(&a,b);
C.f1(a,&b);
D.f1(&a,&b);