資料結構與演算法課程筆記(二)

墨子龜發表於2020-11-01

實驗二 線性表的順序儲存結構實現

一、實驗目的

  1. 熟悉VC++工程專案的檔案組織方式;
  2. 線性表中資料元素間的關係及其順序儲存結構方式表示方法;
  3. 順序表的操作方法與介面函式的設計方法。

二、實驗內容

1. 利用本次實驗提供的檔案(listinarray.h、listinarray.cpp、content.cpp),建立並觀察專案,回答下面問題。

檔案說明: 【listinarray.h】順序表的型別宣告和操作介面宣告 【listinarray.cpp】順序表的操作實現程式碼
【content.cpp】順序表應用程式(main函式)

(1) 程式如何定義順序表的抽象資料型別?
答:程式使用陣列定義順序表的抽象資料型別的集合和關係,陣列元素的插入、刪除、查詢等操作作為運算。

(2) 找出程式中定義順序表抽象資料型別中的資料結構的程式碼?

typedef struct {
  ElemType data[MaxSize]; 
  int length;
} SqList;

(3) 找出程式中定義順序表抽象資料型別中的操作介面的程式碼?

//初始化空線性表
void InitList(SqList &L);
//判斷線性表是否為空
bool ListEmpty(SqList L);
//求出線性表長度
int ListLength(SqList L);
//向線性表指定位置插入一個新元素
bool ListInsert(SqList &L, int pos, ElemType item);
//從線性表中刪除第一個與指定值匹配的元素
bool ListDelete(SqList &L, int pos, ElemType &item);
//獲取順序表中指定位置上的資料元素
bool GetElem(SqList L, int pos, ElemType &item);
//從線性表中查詢元素,返回第一個與指定值匹配元素位置
int Find(SqList L, ElemType item);
//遍歷輸出線性表
void TraverseList(SqList L);
//合併線性表
void MergeList(SqList &L1, SqList L2);
//降序合併線性表
void MergeList_Sq(SqList  La, SqList  Lb, SqList  &Lc);

(4) 在標頭檔案中找出順序表資料元素型別宣告的程式碼,並指出當前程式中的順序表的資料元素是什麼型別的資料?假設在順序表中儲存的資料元素要更改為字元時該如何修改程式碼?
答:typedef int ElemType; //宣告元素型別
順序表中的資料元素是整型的資料,若要更改為字元型別時,程式碼可修改為:typedef char ElemType;

(5) 程式中是如何表示順序表中相鄰資料元素的約束關係,即如何確定順序表中的資料元素的相鄰關係?
答:陣列的每個元素在計算機的儲存空間是依次連續的。

(6) 修改主函式main( )的程式碼,並按下圖輸出資料:
在這裡插入圖片描述
"listinarray.h"檔案中修改線性表元素型別:

typedef   int   ElemType;

"content.cpp"檔案中修改以下程式碼:

#include "listinarray.h"
int main()
{
 	SqList my_List2; //定義線性表SqList型別的變數
	ElemType Array[] ={1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1};![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201101203043200.png#pic_center)

  	for (int i = 1; i <= 20; i++)
    	ListInsert(my_List2, i, Array[i - 1]);
    cout << "my_list2:";
  	TraverseList(my_List2);
 	return 0;
}

(7) 修改順序表的元素型別,輸入相應資料,並按下圖輸出資料:

在這裡插入圖片描述
"listinarray.h"檔案中修改線性表元素型別:

typedef int ElemType;

"content.cpp"檔案中修改以下程式碼:

#include "listinarray.h"
int main()
{
	SqList my_List2; //定義線性表SqList型別的變數
  	ElemType Array[] = "student";
  	InitList(my_List2);
 	for (int i = 1; i <= 7; i++)
 	   ListInsert(my_List2, i, Array[i - 1]);
  	cout << "my_list2:";
  	TraverseList(my_List2);
  	return 0;
}

2. 重新設計一個主程式完成如下功能:
(1) 初始化順序表my_list;
(2) 在my_list的頭部依次插入’a’, ‘b’, ‘c’, ‘d’, 'e’元素;
(3) 輸出my_list的長度及my_list中的元素;
(4) 判斷my_list是否為空;
(5) 在my_list第4個位置上插入元素 'f ’ 並輸出my_list;
(6) 刪除my_list的第3個元素並輸出被刪除元素和my_list;
(7) 輸出my_list的第2個元素;
(8) 輸出元素 ‘b’ 的位置。

#include "listinarray.h"

int main()
{
  SqList my_list; //定義線性表SqList型別的變數
  ElemType Array[] = {'a','b','c','d','e'};
  ElemType b[1] = {};
  //1初始化線性表
  InitList(my_list);
  
  //2在my_list的頭部依次插入a, b, c, d, e元素 
  for (int i = 1; i <= 5; i++)
	  ListInsert(my_list, i, Array[i - 1]);
	  
  //3輸出線性表元素
  cout << "my_list長度為:" << ListLength(my_list) << endl;
  cout << "my_list元素為:";
  
  //4判斷my_list是否為空
  TraverseList(my_list);
  cout << "my_list是否為空:"<< ListEmpty(my_list) << endl;
  
  //5在my_list第4個位置上插入元素f
  ListInsert(my_list, 4, 'f');
  cout << "my_list第四個位置上插入元素f:";
  TraverseList(my_list);
  
  //6刪除my_list的第3個元素
  ListDelete(my_list, 3, b[0]);
  cout << "被刪除的元素:"<<b[0]<<endl;
  cout << "刪除元素後的my_list:";
  TraverseList(my_list);
  
  //7輸出my_list的第二個元素
  GetElem(my_list, 2, b[1]);
  cout << "my_list的第2個元素:" << b[1] << endl;
  
  //8輸出元素’b’的位置
  cout << "my_list的'b'的位置:" << Find(my_list,'b') << endl;

  return 0;
}

3. 設計順序表的介面函式void MergeList(SqList &L1 , SqList L2); 把順序表L2中的資料全部合併到順序表L1的尾部。如下所示:L1中有資料{1,2,3,4,5},L2中有資料 {6,7,8,9,10};合併的結果為L1中包含資料 {1,2,3,4,5, 6,7,8,9,10}。執行結果如下圖所示。
在這裡插入圖片描述

// ①(ListInArray.h)檔案中新增
//合併線性表L2到線性表L1尾部
void MergList(SqList &L1 ,SqList L2);

//修改線性表元素型別ElemType
typedef int ElemType;

// ②(ListInArray.cpp)檔案中新增
//合併線性表L2到線性表L1尾部
void MergList(SqList &L1 ,SqList L2)
{
	ElemType t;
	for(int i=1;i<= ListLength(L2);i++)
	{
		GetElem(L2, i, t);
		ListInsert(L1, ListLength(L1)+1, t);
	}
}
// ③(content.cpp)檔案中
#include "listInarray.h"
int main()
{
	SqList	my_List1,my_List2;
	InitList(my_List1);
	InitList(my_List2);

	for(int i=1;i<=5;i++)
	{
		ListInsert(my_List1, i, i);
		ListInsert(my_List2, i, i+5);
	}
	cout<<"線性表my_List1中有資料:"<<endl;
	TraverseList(my_List1);
	
	cout<<"線性表my_List2中有資料:"<<endl;
	TraverseList(my_List2);

	MergList(my_List1, my_List2);

	cout<<"合併後的線性表my_List1中有資料:"<<endl;
	TraverseList(my_List1);
	return 0;
}

思考題:
已知順序表 La 、 Lb中的元素按非遞減順序排列。請思考並設計一個函式 void MergeList_Sq(SqList La, SqList Lb, SqList &Lc) ,把La和Lb中的元素合併到一個順序表Lc,使Lc中的元素也保持非遞減順序排列。
如: La={2,4,7,9} Lb={3,5,7,10,12}
合併後: Lc={2,3,4,5,7,7,9,10,12}

ListInArray.h:

void MergeList_Sq(SqList  La,  SqList  Lb,  SqList  &Lc);

ListInArray.cpp:

void MergeList_Sq(SqList  La,  SqList  Lb,  SqList  &Lc)
{
	ElemType a,b;
	int i=1,j=1;

	while(i<= ListLength(La) && j<= ListLength(Lb))
	{
		GetElem(La, i, a);
		GetElem(Lb, j, b);
		if(a<=b)
		{  
			ListInsert(Lc, ListLength(Lc)+1, a);
			i++;
		}
		else
		{  
			ListInsert(Lc, ListLength(Lc)+1, b);
			j++;
		}
	}

	while(i<= ListLength(La))
	{  
		GetElem(La, i, a);
		ListInsert(Lc, ListLength(Lc)+1, a);
		i++;
	}

	while(j<= ListLength(Lb))
	{  
		GetElem(Lb, j, b);
		ListInsert(Lc, ListLength(Lc)+1, b);
		j++;
	}
}

content.cpp:

int main()
{

	SqList La,Lb,Lc;//定義線標表SqList型別的變數
	ElemType a[]={2,4,7,9};
	ElemType b[]={3,5,7,10,12};

	//初始化線性表
	InitList(La);
	InitList(Lb);
	InitList(Lc);

	//向線性表的指定位置插入資料
	for(int i=1; i<=sizeof(a)/sizeof(a[0]); i++)
		ListInsert(La, i, a[i-1]);
	
	for(int j=1; j<=sizeof(b)/sizeof(b[0]); j++)
		ListInsert(Lb, j, b[j-1]);

	//輸出線性表元素
	cout<<"La:";
	TraverseList(La);
	cout<<"Lb:";
	TraverseList(Lb);

	cout<<"有序合併後:"<<endl;
	MergeList_Sq(La,Lb,Lc);
	cout<<"Lc:";
	TraverseList(Lc);
	
	return 0;
}

相關文章