鏈表題目


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;
}
  • 若已建立下面的鏈表結構,指針 pq 分別指向圖中所示結點,則不能將 q 所指結點插入到鏈表末尾的語句是(C )。

1.jpg

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM