1. 程式人生 > >資料結構實驗2:C++實現單鏈表類

資料結構實驗2:C++實現單鏈表類

       太簡單了,沒啥可說的,程式碼意義明白如話。

       題目與要求:

                                                         實驗2

     2.1 實驗目的

       熟練掌握線性表的鏈式儲存結構。

       熟練掌握單鏈表的有關演算法設計。

       根據具體問題的需要,設計出合理的表示資料的鏈式儲存結構,並設計相關演算法。

     2.2 實驗要求

      本次實驗中的連結串列結構指帶頭結點的單鏈表;

      單鏈表結構和運算定義,演算法的實現以庫檔案方式實現,不得在測試主程式中直接實現;

      比如儲存、演算法實現放入檔案:linkedList.h

      實驗程式有較好可讀性,各運算和變數的命名直觀易懂,符合軟體工程要求;

      程式有適當的註釋。

    2.3 實驗任務

       編寫演算法實現下列問題的求解。

       <1>尾插法建立單鏈表,列印建立結果。

       <2>頭插法建立單鏈表,列印建立結果。

       <3>銷燬單鏈表。

       <4>求連結串列長度。

       <5>求單鏈表中第i個元素(函式),若不存在,報錯。

       實驗測試資料基本要求:

       第一組資料:單鏈表長度n≥10,i分別為5,n,0,n+1,n+2

       第二組資料:單鏈表長度n=0,i分別為0,2

       <6>在第i個結點前插入值為x的結點。

        實驗測試資料基本要求:

        第一組資料:單鏈表長度n≥10,x=100,  i分別為5,n,n+1,0,1,n+2

        第二組資料:單鏈表長度n=0,x=100,i=5

       <7>連結串列中查詢元素值為x的結點,成功返回結點指標,失敗報錯。

       實驗測試資料基本要求:

       單鏈表元素為(1,3,6,10,15,16,17,18,19,20)

       x=1,17,20,88

       <8>刪除單鏈表中第i個元素結點。

       實驗測試資料基本要求:

       第一組資料:單鏈表長度n≥10,i分別為5,n,1,n+1,0

       第二組資料:單鏈表長度n=0, i=5

       <9>在一個遞增有序的單鏈表L中插入一個值為x的元素,並保持其遞增有序特性。

       實驗測試資料基本要求:

       單鏈表元素為(10,20,30,40,50,60,70,80,90,100),

       x分別為25,85,110和8

       <10>將單鏈表L中的奇數項和偶數項結點分解開(元素值為奇數、偶數),分別放入新的單鏈表中,然後原表和新表元素同時輸出到螢幕上,以便對照求解結果。

       實驗測試資料基本要求:

       第一組資料:單鏈表元素為(1,2,3,4,5,6,7,8,9,10,20,30,40,50,60)

       第二組資料:單鏈表元素為(10,20,30,40,50,60,70,80,90,100)

     2.5 執行結果截圖及說明

圖1 測試(1)
圖2 測試(2)
圖3 測試(3)
圖4 測試(4)
圖5 測試(5)
圖6 測試(5)
圖7 測試(6)①
圖8 測試(6)②
圖9 測試(7)
圖10 測試(8)①
圖11 測試(8)②
圖12 測試(9)
圖13 測試(10)①
圖14 測試(10)②

      2.6 附原始碼

       單鏈表C++整體描述框架:

// linkedList1.h: interface for the linkedList class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_LINKEDLIST1_H__4C3F34C9_D36C_43D6_97CF_A8E55FD6BD7D__INCLUDED_)
#define AFX_LINKEDLIST1_H__4C3F34C9_D36C_43D6_97CF_A8E55FD6BD7D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "StdAfx.h"

using namespace std;

class linkedList  
{
public:
	linkedList();//建構函式
	virtual ~linkedList();//解構函式,銷燬單鏈表
	bool createLinkedListRail( int length );//尾插法構建單鏈表
	bool createLinkedListFront( int length );//頭插法構建單鏈表
	void addLinkedListNodeLast( int value );//警告:必須初始化才能使用!
	//我嘗試判斷呼叫物件的連結串列是否初始化來作為是否呼叫該函式的依據,結果失敗:無論如何判斷,總是不能在零節點時插入
	bool initiateLinkedList();//初始化單鏈表
	bool isEmpty();//判斷單鏈表是否為空
	bool getElementByPosition( int pos, int& value );//求單鏈表中第pos個元素(函式),若不存在,報錯
	bool insertListByPosition( int pos, int value );//在第pos個結點前插入值為value的結點
	bool getElementByValue( int& pos, int value );//連結串列中查詢元素值為x的結點,成功返回結點指標,失敗報錯。
	bool removeListNodeByPosition( int pos, int& value );//刪除單鏈表中第pos個元素結點
	bool insertListSort( int value );//在一個遞增有序的單鏈表L中插入一個值為value的元素,並保持其遞增有序特性
	bool oddEvenSort( linkedList& LA,linkedList& LB );//將呼叫單鏈表中的元素按奇偶性分配給被呼叫的單鏈表LA與LB
	void printLinkedList();//列印單鏈表
	int linkedListLength();//返回單鏈表長度
private:
	LList *head;
	int len;
};

#endif // !defined(AFX_LINKEDLIST1_H__4C3F34C9_D36C_43D6_97CF_A8E55FD6BD7D__INCLUDED_)
// linkedList1.cpp: implementation of the linkedList class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "linkedList1.h"


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

linkedList::linkedList()
{
	head = NULL;
	len = 0;
}

linkedList::~linkedList()
{
	LList* tmp = head;
	//for( int i = 0; i < len; i ++ )
	while( tmp->next )
	{
		LList *q = tmp;
		tmp = tmp->next;
		delete q;
	}
}

bool linkedList::initiateLinkedList()
{
	std::ios::sync_with_stdio(false);
	head = new LList;
	if( !head )
	{
		cout << "初始化失敗!" << endl;
		return false;
	}
	head->next = NULL;
	return true;
}

bool linkedList::createLinkedListRail( int length )
{
	std::ios::sync_with_stdio(false);
	initiateLinkedList();
	LList* rail = head;
	for( int i = 1; i <= length; i ++ )
	{
		LList* tmp = new LList;
		int num;
		cin >> num;
		//num = i + 1;
		tmp->data = num;
		tmp->next = rail->next;
		rail->next = tmp;
		rail = tmp;
		len ++;
	}
	return true;
}

bool linkedList::createLinkedListFront( int length )
{
	std::ios::sync_with_stdio(false);
	initiateLinkedList();
	for( int i = 0; i < length; i ++ )
	{
		int num;
		cin >> num;
		//num = i + 1;
		LList* tmp = new LList;
		tmp->data = num;
		tmp->next = head->next;
		head->next = tmp;
		len ++;
	}
	return true;
}

void linkedList::addLinkedListNodeLast( int value )
{
	//ios::sync_with_stdio(false);
	
	LList* tmp = head;
	LList* last = NULL;
	while(tmp)
	{
		last = tmp;
		tmp = tmp->next;
	}
	LList* PNew = new LList;
	PNew->data = value;
	PNew->next = NULL;
	last->next = PNew;
	len ++;
}

bool linkedList::isEmpty()
{
	return head->next == NULL;
}

void linkedList::printLinkedList()
{
	std::ios::sync_with_stdio(false);
	if( isEmpty() )
	{
		cout << "空連結串列,無法列印!" << endl;
		return;
	}
	LList* tmp = head->next;
	int column = 0;
	while(tmp)
	{
		cout << setiosflags(ios::left) << setw(3) << tmp->data << " ";
		column ++;
		if( column % 10 == 0 )
			cout << endl;
		tmp = tmp->next;
	}
	cout << endl;
}

int linkedList::linkedListLength()
{
	if( isEmpty() )
	{
		cout << "空連結串列!" << endl;
		return -1;
	}
	int l = 0;
	LList* tmp = head->next;
	while(tmp)
	{
		tmp = tmp->next;
		l ++;
	}
	return l;
	//return len;
}

bool linkedList::getElementByPosition( int pos, int& value )
{
	ios::sync_with_stdio(false);
	if( isEmpty() )
	{
		cout << "連結串列為空!獲取元素失敗!" << endl;
		return false;
	}
	if( pos > len )
	{
		cout << "位置大於表長!獲取元素失敗!" << endl;
		return false;
	}
	if( pos <= 0 )
	{
		cout << "位置必須大於0!獲取元素失敗!" << endl;
		return false;
	}
	int index = 0;
	LList* tmp = head;
	while(tmp)
	{
		if( index == pos )
		{
			//cout << tmp->data;
			value = tmp->data;
			return true;
		}
		tmp = tmp->next;
		index ++;
	}
	return true;
}

bool linkedList::insertListByPosition( int pos, int value )
{
	ios::sync_with_stdio(false);
	if( isEmpty() )
	{
		cout << "連結串列為空!插入元素失敗!" << endl;
		return false;
	}
	else if( pos > len )
	{
		cout << "位置大於表長且差值大於1!刪除元素失敗!" << endl;
		return false;
	}
	else if( pos == len )
	{
		cout << "將會直接把新節點接在連結串列尾部!" << endl;
		addLinkedListNodeLast( value );
		return true;
	}
	else if( pos <= 0 )
	{
		cout << "位置必須大於0!插入元素失敗!" << endl;
		return false;
	}
	int index = 0;
	LList* tmp = head;
	while( index != pos - 1 && tmp )
	{
		index ++;
		tmp = tmp->next;
	}
	if( tmp == NULL )
	{
		cout << "位置大於表長且不在表長的後一位!插入元素失敗!" << endl;
		return false;
	}
	LList* PNew = new LList;
	PNew->data =  value;
	PNew->next = tmp->next;
	tmp->next = PNew;
	len ++;
	return true;
}

bool linkedList::getElementByValue( int& pos, int value )
{
	ios::sync_with_stdio(false);
	if( isEmpty() )
	{
		cout << "連結串列為空!獲取元素失敗!" << endl;
		return false;
	}
	int index = 1;
	LList* tmp = head->next;
	while(tmp)
	{
		if( tmp->data == value )
		{
			pos = index;
			return true;
		}
		tmp = tmp->next;
		index ++;
	}
	return false;
}

bool linkedList::removeListNodeByPosition( int pos, int& value )
{
	ios::sync_with_stdio(false);
	if( isEmpty() )
	{
		cout << "連結串列為空!刪除元素失敗!" << endl;
		return false;
	}
	if( pos > len )
	{
		cout << "位置大於表長!刪除元素失敗!" << endl;
		return false;
	}
	if( pos <= 0 )
	{
		cout << "位置必須大於0!刪除元素失敗!" << endl;
		return false;
	}
	LList* tmp = head;
	int index = 0;
	while( index != pos - 1 && tmp )
	{
		tmp = tmp->next;
		index ++;
	}
	LList* PDel = tmp->next;
	value = PDel->data;
	tmp->next = tmp->next->next;
	delete PDel;
	len --;
	return true;
}

bool linkedList::insertListSort( int value )
{
	ios::sync_with_stdio(false);
	if( isEmpty() )
	{
		cout << "連結串列為空!插入元素失敗!" << endl;
		return false;
	}
	LList* tmp = head;
	while( tmp->next && tmp->next->data < value )//下一個節點的data比value小就繼續迴圈
	//寫成下面這樣導致比最後一個節點的data大的value無法插入!因為迴圈結束時tmp->next為NULL,無法插入。
	//while( tmp && tmp->next->data < value )
	{
		//if( tmp->data < value )
			tmp = tmp->next;
	}
	LList* PNew = new LList;
	PNew->data = value;
	PNew->next = tmp->next;
	tmp->next = PNew;
	return true;
}

bool linkedList::oddEvenSort( linkedList& LA,linkedList& LB )
{
	ios::sync_with_stdio(false);
	if( isEmpty() )
	{
		cout << "原連結串列為空!分配元素失敗!" << endl;
		return false;
	}
	//if( !LA.head->next && !LB.head->next )
	if( !LA.head && !LB.head )
	{
		LA.initiateLinkedList();
		LB.initiateLinkedList();
	}
	LList* tmp = head->next;
	while(tmp)
	{
		if( tmp->data >= 0 && ( tmp->data & 1 ) )
			LA.addLinkedListNodeLast( tmp->data );
		//else if( tmp->data >= 0 && !( tmp->data & 1 ) )
		else
			LB.addLinkedListNodeLast( tmp->data );
		tmp = tmp->next;
	}
	return true;
}

       測試函式:

// LinkedList.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "linkedList1.h"

int main(int argc, char* argv[])
{
	ios::sync_with_stdio(false);
	freopen( "1.in", "r", stdin );
	
	linkedList L1;//, L2;
	int n;
	cin >> n;
	L1.createLinkedListFront(n);
	cout << "原表表長為:" << endl;
	cout << L1.linkedListLength() << endl;
	cout << "原表元素為:" << endl;
	L1.printLinkedList();
	/*
	L1.~linkedList();
	cout << "現表表長為:" << endl;
	cout << L1.linkedListLength() << endl;
	cout << "現表元素為:" << endl;
	L1.printLinkedList();
	//L2.createLinkedListFront(5);
	//cout << L2.linkedListLength() << endl;
	//L2.printLinkedList();
	22
	30 70 92 91 15 47 84 10 43 34 9 62 60 26 79 96 38 4 92 24 25 5
	
	linkedList L3;
	int n;
	cin >> n;
	L3.createLinkedListRail(n);
	cout << "原表表長為:" << endl;
	cout << L3.linkedListLength() << endl;
	cout << "原表元素為:" << endl;
	L3.printLinkedList();//5,n,0,n+1,n+2
	
	int value = -100;
	int num;
	cin >> num;
	for( int i = 0; i < num; i ++ )
	{
		int pos;
		cin >> pos;
		if( L3.getElementByPosition( pos, value ) )
		{
			cout << "第 " << pos << " 個元素的值為:" << value << endl;

		}
		else
			cout << "不存在位置為 " << pos << " 的元素!" << endl;
	}

	linkedList L4;
	int n;
	cin >> n;
	L4.createLinkedListRail(n);
	cout << "原表表長為:" << endl;
	cout << L4.linkedListLength() << endl;
	cout << "原表元素為:" << endl;
	L4.printLinkedList();//x=100,  i分別為5,n,n+1,0,1,n+2
	int value = 100;
	int num;
	cin >> num;
	for( int i = 0; i < num; i ++ )
	{
		int pos;
		cin >> pos;
		if( L4.insertListByPosition( pos, value ) )
		{
			cout << "value = " << value << " 的值已插在 pos = " << pos << "的位置上!" << endl;
			cout << "現表表長為:" << endl;
			cout << L4.linkedListLength() << endl;
			cout << "現表元素為:" << endl;
			L4.printLinkedList();
		}
	}
	
	linkedList L5;
	int n;
	cin >> n;
	L5.createLinkedListRail(n);
	cout << "原表表長為:" << endl;
	cout << L5.linkedListLength() << endl;
	cout << "原表元素為:" << endl;
	L5.printLinkedList();
	int index = -1;
	//1,17,20,88
	for( int i = 0; i < 4; i ++ )
	{
		int value;
		cin >> value;
		if( L5.getElementByValue( index, value ) )
		{
			cout << "pos = " << index << ", value = " << 1 << endl;
		}
	
		else
		{
			cout << "連結串列中不存在值為 " << value << " 的值" << endl;  
		}
	}
	
	linkedList L6;
	int n;
	cin >> n;
	L6.createLinkedListRail(n);
	L6.printLinkedList();
	cout << L6.linkedListLength() << endl;
	int value = -1;
	//5,n,1,n+1,0 
	if( L6.removeListNodeByPosition( 5, value ) )
	{
		cout << "pos = " << 5 << ", value = " << value << "已刪除!" << endl;
	}
	L6.printLinkedList();
	if( L6.removeListNodeByPosition( n , value ) )
	{
		cout << "pos = " << n << ", value = " << value << "已刪除!" << endl;
	}
	else
	{
		cout << "不存在位置等於 " << n << " 的元素!" << endl;
	}
	L6.printLinkedList();
	if( L6.removeListNodeByPosition( 1, value ) )
	{
		cout << "pos = " << 1 << ", value = " << value << "已刪除!" << endl;
	}
	L6.printLinkedList();
	if( L6.removeListNodeByPosition( n + 1, value ) )
	{
		cout << "pos = " << n + 1 << ", value = " << value << "已刪除!" << endl;
	}
	else
	{
		cout << "不存在位置等於 " << n + 1 << " 的元素!" << endl;
	}
	L6.printLinkedList();
	if( L6.removeListNodeByPosition( 0, value ) )
	{
		cout << "pos = " << 0 << ", value = " << value << "已刪除!" << endl;
	}
	else
	{
		cout << "不存在位置等於 " << 0 << " 的元素!" << endl;
	}
	L6.printLinkedList();

	
	linkedList L7;
	int n;
	cin >> n;
	L7.createLinkedListRail(n);
	cout << "原表表長為:" << endl;
	cout << L7.linkedListLength() << endl;
	cout << "原表元素為:" << endl;
	L7.printLinkedList();
	
	//int value = -1;
	//5,n,1,n+1,0 
	for( int i = 0; i < 1; i ++ )
	{
		int value;
		cin >> value;
		if( L7.removeListNodeByPosition( 5, value ) )
		{
			cout << "pos = " << 5 << ", value = " << value << "已刪除!" << endl;
			cout << "現表表長為:" << endl;
			cout << L7.linkedListLength() << endl;
			cout << "現表元素為:" << endl;
			L7.printLinkedList();
		}
		if( L7.removeListNodeByPosition( n , value ) )
		{
			cout << "pos = " << n << ", value = " << value << "已刪除!" << endl;
		}
		else
		{
			cout << "不存在位置等於 " << n << " 的元素!" << endl;
		}
	}
	
	linkedList L8;
	int n;
	cin >> n;
	L8.createLinkedListRail(n);
	cout << "原表表長為:" << endl;
	cout << L8.linkedListLength() << endl;
	
	cout << "原表元素為:" << endl;
	L8.printLinkedList();
	int value;
	for( int i = 0; i < 4; i ++ )
	{
		cin >> value;
		if( L8.insertListSort(value) )
		{
			cout << "插入元素 " << value << " 後表長為:" << endl;
			cout << L8.linkedListLength() << endl;
			cout << "插入元素 " << value << " 表元素為:" << endl;
			L8.printLinkedList();
		}
		else
			cout << "Error!" << endl;
	}
	
	int n;
	linkedList L9, LA, LB;
	cin >> n;
	L9.createLinkedListRail(n);
	//LA.initiateLinkedList(), LB.initiateLinkedList();
	cout << "原連結串列表長為:" << endl;
	cout << L9.linkedListLength() << endl;
	cout << "原連結串列元素為:" << endl;
	L9.printLinkedList();
	L9.oddEvenSort( LA, LB );
	cout << "奇數連結串列表長為:" << endl;
	cout << LA.linkedListLength() << endl;
	cout << "奇數連結串列元素為:" << endl;
	LA.printLinkedList();
	cout << "偶數連結串列表長為:" << endl;
	cout << LB.linkedListLength() << endl;
	cout << "偶數連結串列元素為:" << endl;
	LB.printLinkedList();
	*/
	return 0;
}

       我覺得用重定向的檔案讀寫來除錯,效率更高。因此下面貼一下測試資料,凡是題目有提供資料的都按照上面的來:

//1
/*
22
30 70 92 91 15 47 84 10 43 34 9 62 60 26 79 96 38 4 92 24 25 5
*/

//2
/*
22
30 70 92 91 15 47 84 10 43 34 9 62 60 26 79 96 38 4 92 24 25 5*
/

//3
/*
22
30 70 92 91 15 47 84 10 43 34 9 62 60 26 79 96 38 4 92 24 25 5
*/

//4
/*
22
30 70 92 91 15 47 84 10 43 34 9 62 60 26 79 96 38 4 92 24 25 5
*/

//5.1
/*
20
30 70 92 91 15 47 84 10 43 34 9 62 60 26 79 96 38 4 92 24
5
5 20 0 21 22
*/

//5.2
/*
0
2
0 2
*/

//6.1
/*
20
30 70 92 91 15 47 84 10 43 34 9 62 60 26 79 96 38 4 92 24
6
5 20 21 0 1 22
*/

//6.2
/*
0
1
5
*/

//7.1
/*
10
1 3 6 10 15 16 17 18 19 20
1 17 20 88
*/

//7.2
/*
0
*/

//8.1
/*
20
30 70 92 91 15 47 84 10 43 34 9 62 60 26 79 96 38 4 92 24
5 20 1 21 0
*/

//8.2
/*
0
5
*/

//9
/*
10
10 20 30 40 50 60 70 80 90 100
25 85 110 8
*/

//10.1
/*
15
1 2 3 4 5 6 7 8 9 10 20 30 40 50 60
*/

//10.2
/*
10
10 20 30 40 50 60 70 80 90 100
*/