資料結構-實驗一 鏈式儲存結構的基本操作
廣州大學學生實驗報告
開課實驗室:電腦科學與工程實驗(電子樓417) 2018年5月09日
學院 |
電腦科學與教育軟體學院 |
年級、專業、班 |
網路161 |
姓名 |
卟咚君 |
學號 |
1606100*** |
|
實驗課程名稱 |
資料結構實驗 |
成績 |
||||||
實驗專案名稱 |
實驗一 鏈式儲存結構的基本操作 |
指導老師 |
** |
|||||
一、實驗目的 掌握線性的定義及基本操作,用連結串列實現:遍歷、查詢、插入、刪除、翻轉。 二、使用儀器、器材 微機一臺 作業系統:WinXP 程式設計軟體:C++ 三、實驗內容及原理 (1)用隨機函式生成8個3位整數(100~999),把這些整數存於連結串列中; (2)輸出連結串列的內容; (3)讀入一個整數,檢視該整數是否在表中,若在,輸出其位置(首位置為1); (4)讀入一個整數,以及要插入的位置,把該整數插入到連結串列中,輸出連結串列的內容(要求判斷輸入的位置是否合理); (5)讀入一個整數,若該整數在連結串列裡,刪除該整數,輸出連結串列的內容; (6)把連結串列的內容翻轉,輸出連結串列的內容。 思路:通過定義一個class類 ListNode,表示連結串列的結點; 通過定義一個class類 SingleList ,表示連結串列,封裝了對連結串列的各種操作: void MakeEmpty(); //清空連結串列 int Length(); //返回連結串列的長度 int Find(Type item); //在連結串列中查詢資料item,找到則返回相應連結串列結點的位置,否則返回-1 bool Insert(Type item, int n ); //在位置n的結點前插入一個新結點,新結點的data值為item ListNode<Type>* Get(int pos); //查詢連結串列的第n個連結串列結點,返回連結串列結點的指標 bool Remove(int n); //刪除第n個連結串列結點 void Rollback(); //對連結串列的內容進行翻轉 void Print(); //輸出連結串列的內容 原始碼: #include<iostream> #include<ctime> #include<cmath> using namespace std; template<typename Type> class ListNode{ public: ListNode() :data(0), next(NULL){} ListNode(const Type item, ListNode<Type> *next = NULL) :data(item), next(next){} ~ListNode(){ next = NULL; } public: Type GetData(); friend ostream& operator<< <Type>(ostream&, ListNode<Type>&); Type data; ListNode *next; }; template<typename Type> Type ListNode<Type>::GetData(){ return this->data; } template<typename Type> ostream& operator<<(ostream& os, ListNode<Type>& out){ os << out.data; return os; } template<typename Type> class SingleList{ public: SingleList() :head(new ListNode<Type>()), len(0){} ~SingleList(){ MakeEmpty(); delete head; } public: void MakeEmpty(); //清空連結串列 int Length(); //返回連結串列的長度 int Find(Type item); //在連結串列中查詢資料item,找到則返回相應連結串列結點的位置,否則返回-1 bool Insert(Type item, int n); //在位置n的結點前插入一個新結點,新結點的data值為item ListNode<Type>* Get(int pos); //查詢連結串列的第n個連結串列結點,返回連結串列結點的指標 bool Remove(int n); //刪除第n個連結串列結點 void Rollback(); //對連結串列的內容進行翻轉 void Print(); //輸出連結串列的內容 private: ListNode<Type> *head; //連結串列的表頭,不儲存資料data int len; //連結串列的長度 }; template<typename Type> void SingleList<Type>::MakeEmpty(){ //清空連結串列 ListNode<Type> *pdel; while (head->next != NULL){ pdel = head->next; head->next = pdel->next; delete pdel; } } template<typename Type> int SingleList<Type>::Length(){ //返回連結串列的長度 return len; } template<typename Type> int SingleList<Type>::Find(Type item){ //在連結串列中查詢資料item,找到則返回相應連結串列結點的位置,否則返回-1 int pos = 1; ListNode<Type> *pmove = head->next; while (pmove&&pmove->data != item){ pmove = pmove->next; pos++; } if (pmove == NULL) pos = -1; return pos; } template<typename Type> ListNode<Type>* SingleList<Type>::Get(int n){ //查詢連結串列的第n個連結串列結點,返回連結串列結點的指標 if (n <= 0 || n>len){ cout << "請輸入合法的資料下標" << endl; return NULL; } ListNode<Type> *pmove = head->next; int pos = 1; while (pos != n&&pmove){ pmove = pmove->next; pos++; } return pmove; } template<typename Type> bool SingleList<Type>::Remove(int n){ //刪除第n個連結串列結點 if (n <= 0){ cout << "請輸入合理的下標位置" << endl; exit(1); } ListNode<Type> *pmove = head->next, *pdel; for (int i = 1; i<n&&pmove->next; i++){ pmove = pmove->next; } if (pmove->next == NULL){ cout << "查詢到的下標超出連結串列" << endl; exit(1); } pdel = pmove->next; pmove->next = pdel->next; delete pdel; cout << "刪除成功第" << n << "個連結串列結點成功" << endl; len--; return 1; } template<typename Type> bool SingleList<Type>::Insert(Type item, int n){ //在位置n的結點前插入一個新結點,新結點的data值為item if (n <= 0 || n>len + 1){ cout << "請輸入合理的下標位置" << endl; return 0; } ListNode<Type> *pmove = head; ListNode<Type> *pnode = new ListNode<Type>(item); for (int i = 1; i<n&&pmove; i++){ pmove = pmove->next; } len++; pnode->next = pmove->next; pmove->next = pnode; cout << "在第" << n << "位插入" << item << "成功" << endl; return 1; } template<typename Type> void SingleList<Type>::Print(){ //輸出連結串列的內容 ListNode<Type> *pmove = head->next; cout << "head"; while (pmove){ cout << "--->" << pmove->data; pmove = pmove->next; } cout << "--->over" << endl; } template<typename Type> void SingleList<Type>::Rollback(){ //對連結串列的內容進行翻轉 for (int i = 1; i <= len / 2; i++){ ListNode<Type> *node1 = Get(i); ListNode<Type> *node2 = Get(len - i + 1); Type num = node1->data; node1->data = node2->data; node2->data = num; } cout << "翻轉成功" << endl; } int main(){ time_t t; srand((unsigned)time(&t)); //由時間確定隨機序列,執行一次 SingleList<int> Slist; //定義一個單鏈表 for (int i = 1; i <= 8; i++){ //(1)隨機函式生成100~999的資料存入單鏈表中 Slist.Insert(rand() % 900 + 100, i); } Slist.Print(); //(2)輸出連結串列的內容; bool flag; int num,pos; cout << "如果要判斷一個數是否在連結串列中,請輸入任意非零數進入判斷,否則跳過該判斷請輸入0:"; cin >> flag; while (flag){ cout << "讀入一個數據,判斷是否在連結串列中:"; //(3)讀入一個整數,檢視該整數是否在表中,若在,輸出其位置(首位置為1); cin >> num; //讀入一個數據 pos = Slist.Find(num); //pos等於資料在連結串列中的位置 if (pos != -1){ //pos若等於-1,則表示不在連結串列中 cout << "該資料在連結串列中的第" << pos << "個連結串列結點的位置" << endl; } else{ cout << "該資料不在連結串列中" << endl; } cout << "如果要判斷一個數是否在連結串列中,請輸入任意非零數進入判斷,否則跳過該判斷請輸入0:"; cin >> flag; } cout << "如果要插入一個數進入連結串列中,請輸入任意非零數進入插入,否則跳過該次插入請輸入0:"; cin >> flag; while (flag){ cout << "讀入一個數據和一個插入的位置,插入到連結串列中:"; //(4)讀入一個整數,以及要插入的位置,把該整數插入到連結串列中,輸出連結串列的內容(要求判斷輸入的位置是否合理); cin >> num >> pos; //讀入一個數據和要插入的位置 Slist.Insert(num, pos); //在單鏈表的第pos位置插入資料num,插入時會在函式Slist.Insert(num, pos)中判斷插入的位置是否合理 Slist.Print(); //輸出單鏈表的資料 cout << "如果要插入一個數進入連結串列中,請輸入任意非零數進入插入,否則跳過該次插入請輸入0:"; cin >> flag; } cout << "如果要刪除連結串列一個數據,請輸入任意非零數進入刪除,否則跳過該次刪除請輸入0:"; cin >> flag; while (flag){ cout << "讀入一個數據,若在連結串列中則刪除它:"; //(5)讀入一個整數,若該整數在連結串列裡,刪除該整數,輸出連結串列的內容; cin >> num; //讀入一個數據 pos = Slist.Find(num); //pos等於資料在連結串列中的位置 if (pos != -1){ //若pos!=-1,則表示在連結串列中存在 Slist.Remove(pos); //刪除對應pos位置的連結串列結點的資料 Slist.Print(); //輸出單鏈表的資料 }//把連結串列的內容翻轉,輸出連結串列的內容。 else{ cout << "該資料不在連結串列中" << endl; } cout << "如果要刪除連結串列一個數據,請輸入任意非零數進入刪除,否則跳過該次刪除請輸入0:"; cin >> flag; } cout << "翻轉後的資料:"; //(6) Slist.Rollback(); //翻轉連結串列 Slist.Print(); //輸出連結串列 return 0; }
通過這次實驗,掌握了線性表的連結串列的遍歷、查詢、插入、刪除、翻轉等基本操作。 通過定義一個class類 ListNode,表示連結串列的結點;通過定義一個class類 SingleList ,表示連結串列,封裝了對連結串列的各種操作:在連結串列SingleList中,表頭不儲存資料,在SingleList插入資料,先判斷是否插入的位置是否合理,合理則插入資料。由於表頭不儲存資料,所以所有的插入方式(表頭插入,中間插入,表尾插入)都可歸結成一種情況解決。而在刪除的過程中,一開始刪除資料後,忘記把連結串列的長度對應的減一,導致翻轉的時候出錯,已改正。刪除的時候也是要要判斷刪除的位置是否合理,合理才刪除。翻轉的時候其實連結串列結點不變,只是按照連結串列中間對稱的方式把頭尾的內容進行交換,以達到翻轉連結串列內容的效果。 |
//原始碼:
#include<iostream>
#include<ctime>
#include<cmath>
using namespace std;
template<typename Type> class ListNode{
public:
ListNode() :data(0), next(NULL){}
ListNode(const Type item, ListNode<Type> *next = NULL) :data(item), next(next){}
~ListNode(){
next = NULL;
}
public:
Type GetData();
friend ostream& operator<< <Type>(ostream&, ListNode<Type>&);
Type data;
ListNode *next;
};
template<typename Type> Type ListNode<Type>::GetData(){
return this->data;
}
template<typename Type> ostream& operator<<(ostream& os, ListNode<Type>& out){
os << out.data;
return os;
}
template<typename Type> class SingleList{
public:
SingleList() :head(new ListNode<Type>()), len(0){}
~SingleList(){
MakeEmpty();
delete head;
}
public:
void MakeEmpty(); //清空連結串列
int Length(); //返回連結串列的長度
int Find(Type item); //在連結串列中查詢資料item,找到則返回相應連結串列結點的位置,否則返回-1
bool Insert(Type item, int n); //在位置n的結點前插入一個新結點,新結點的data值為item
ListNode<Type>* Get(int pos); //查詢連結串列的第n個連結串列結點,返回連結串列結點的指標
bool Remove(int n); //刪除第n個連結串列結點
void Rollback(); //對連結串列的內容進行翻轉
void Print(); //輸出連結串列的內容
private:
ListNode<Type> *head; //連結串列的表頭,不儲存資料data
int len; //連結串列的長度
};
template<typename Type> void SingleList<Type>::MakeEmpty(){ //清空連結串列
ListNode<Type> *pdel;
while (head->next != NULL){
pdel = head->next;
head->next = pdel->next;
delete pdel;
}
}
template<typename Type> int SingleList<Type>::Length(){ //返回連結串列的長度
return len;
}
template<typename Type> int SingleList<Type>::Find(Type item){ //在連結串列中查詢資料item,找到則返回相應連結串列結點的位置,否則返回-1
int pos = 1;
ListNode<Type> *pmove = head->next;
while (pmove&&pmove->data != item){
pmove = pmove->next;
pos++;
}
if (pmove == NULL) pos = -1;
return pos;
}
template<typename Type> ListNode<Type>* SingleList<Type>::Get(int n){ //查詢連結串列的第n個連結串列結點,返回連結串列結點的指標
if (n <= 0 || n>len){
cout << "請輸入合法的資料下標" << endl;
return NULL;
}
ListNode<Type> *pmove = head->next;
int pos = 1;
while (pos != n&&pmove){
pmove = pmove->next;
pos++;
}
return pmove;
}
template<typename Type> bool SingleList<Type>::Remove(int n){ //刪除第n個連結串列結點
if (n <= 0){
cout << "請輸入合理的下標位置" << endl;
exit(1);
}
ListNode<Type> *pmove = head->next, *pdel;
for (int i = 1; i<n&&pmove->next; i++){
pmove = pmove->next;
}
if (pmove->next == NULL){
cout << "查詢到的下標超出連結串列" << endl;
exit(1);
}
pdel = pmove->next;
pmove->next = pdel->next;
delete pdel;
cout << "刪除成功第" << n << "個連結串列結點成功" << endl;
len--;
return 1;
}
template<typename Type> bool SingleList<Type>::Insert(Type item, int n){ //在位置n的結點前插入一個新結點,新結點的data值為item
if (n <= 0 || n>len + 1){
cout << "請輸入合理的下標位置" << endl;
return 0;
}
ListNode<Type> *pmove = head;
ListNode<Type> *pnode = new ListNode<Type>(item);
for (int i = 1; i<n&&pmove; i++){
pmove = pmove->next;
}
len++;
pnode->next = pmove->next;
pmove->next = pnode;
cout << "在第" << n << "位插入" << item << "成功" << endl;
return 1;
}
template<typename Type> void SingleList<Type>::Print(){ //輸出連結串列的內容
ListNode<Type> *pmove = head->next;
cout << "head";
while (pmove){
cout << "--->" << pmove->data;
pmove = pmove->next;
}
cout << "--->over" << endl;
}
template<typename Type> void SingleList<Type>::Rollback(){ //對連結串列的內容進行翻轉
for (int i = 1; i <= len / 2; i++){
ListNode<Type> *node1 = Get(i);
ListNode<Type> *node2 = Get(len - i + 1);
Type num = node1->data;
node1->data = node2->data;
node2->data = num;
}
cout << "翻轉成功" << endl;
}
int main(){
time_t t;
srand((unsigned)time(&t)); //由時間確定隨機序列,執行一次
SingleList<int> Slist; //定義一個單鏈表
for (int i = 1; i <= 8; i++){ //(1)隨機函式生成100~999的資料存入單鏈表中
Slist.Insert(rand() % 900 + 100, i);
}
Slist.Print(); //(2)輸出連結串列的內容;
bool flag;
int num,pos;
cout << "如果要判斷一個數是否在連結串列中,請輸入任意非零數進入判斷,否則跳過該判斷請輸入0:";
cin >> flag;
while (flag){
cout << "讀入一個數據,判斷是否在連結串列中:"; //(3)讀入一個整數,檢視該整數是否在表中,若在,輸出其位置(首位置為1);
cin >> num; //讀入一個數據
pos = Slist.Find(num); //pos等於資料在連結串列中的位置
if (pos != -1){ //pos若等於-1,則表示不在連結串列中
cout << "該資料在連結串列中的第" << pos << "個連結串列結點的位置" << endl;
}
else{
cout << "該資料不在連結串列中" << endl;
}
cout << "如果要判斷一個數是否在連結串列中,請輸入任意非零數進入判斷,否則跳過該判斷請輸入0:";
cin >> flag;
}
cout << "如果要插入一個數進入連結串列中,請輸入任意非零數進入插入,否則跳過該次插入請輸入0:";
cin >> flag;
while (flag){
cout << "讀入一個數據和一個插入的位置,插入到連結串列中:"; //(4)讀入一個整數,以及要插入的位置,把該整數插入到連結串列中,輸出連結串列的內容(要求判斷輸入的位置是否合理);
cin >> num >> pos; //讀入一個數據和要插入的位置
Slist.Insert(num, pos); //在單鏈表的第pos位置插入資料num,插入時會在函式Slist.Insert(num, pos)中判斷插入的位置是否合理
Slist.Print(); //輸出單鏈表的資料
cout << "如果要插入一個數進入連結串列中,請輸入任意非零數進入插入,否則跳過該次插入請輸入0:";
cin >> flag;
}
cout << "如果要刪除連結串列一個數據,請輸入任意非零數進入刪除,否則跳過該次刪除請輸入0:";
cin >> flag;
while (flag){
cout << "讀入一個數據,若在連結串列中則刪除它:"; //(5)讀入一個整數,若該整數在連結串列裡,刪除該整數,輸出連結串列的內容;
cin >> num; //讀入一個數據
pos = Slist.Find(num); //pos等於資料在連結串列中的位置
if (pos != -1){ //若pos!=-1,則表示在連結串列中存在
Slist.Remove(pos); //刪除對應pos位置的連結串列結點的資料
Slist.Print(); //輸出單鏈表的資料
}//把連結串列的內容翻轉,輸出連結串列的內容。
else{
cout << "該資料不在連結串列中" << endl;
}
cout << "如果要刪除連結串列一個數據,請輸入任意非零數進入刪除,否則跳過該次刪除請輸入0:";
cin >> flag;
}
cout << "翻轉後的資料:"; //(6) Slist.Rollback(); //翻轉連結串列
Slist.Print(); //輸出連結串列
return 0;
}
相關推薦
資料結構-實驗一 鏈式儲存結構的基本操作
廣州大學學生實驗報告 開課實驗室:電腦科學與工程實驗(電子樓417) 2018年5月09日 學院 電腦科學與教育軟體學院 年級、專業、班 網路161 姓名
每天一個數據結構----棧的鏈式儲存結構實現(純程式碼)
// // main.c // StackList2 棧的鏈式儲存結構 // // Created by Jacobs.Guo on 2018/4/23. // Copyright © 2018年 yage guo. All rights
資料結構——佇列的鏈式儲存結構以及實現
佇列也是一種特殊的線性表,只允許在一端進行插入操作,在另一端進行刪除操作。允許插入的一段為對尾,允許刪除的一端為隊頭。本次記錄的是佇列的鏈式儲存結構以及實現。該儲存結構有兩個指標,一個指向頭節點,稱為頭指標(front);一個指向隊尾,稱為尾指標(rear)。當
資料結構 串(鏈式儲存)的基本操作
#include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef struct {
資料結構實驗一:線性表的基本操作
// 186658-S181-李雙源.cpp : 定義控制檯應用程式的入口點。 //時間 2018-10-27 //內容:線性表的基本操作 #include "stdafx.h" #include <iostream> #include<s
棧與佇列鏈式儲存結構一貨物上架問題
#include <iostream> #include<string.h> static int n; //用於輸入
《大話資料結構5》—— 佇列的鏈式儲存結構 —— C++程式碼實現
目錄 鏈佇列 迴圈佇列和鏈式佇列的比較 鏈佇列 ● 實現佇列的最好的方式就是使用單鏈表來實現,佇列的鏈式儲存結構,其實就是線性表的單鏈表,只不過它只能尾進頭出而已——稱為鏈佇列。 ● 那為了操作方便,頭指標指向頭結點,隊尾指標指向終端節點,即最後一個結點元
資料結構 筆記:線性表的鏈式儲存結構
鏈式儲存的定義 為了表示每個資料元素與其直接後繼元素之間的邏輯關係;資料元素出了儲存本身的資訊外,還需要儲存直接後繼的資訊。 ps:在邏輯上,元素之間是相鄰的;在實體記憶體中元素之間並無相鄰關係。 鏈式儲存邏輯結構 -基礎鏈式儲存結構的線性表中,每個節點都包含資料域和指標域 ·資
資料結構線性表之鏈式儲存結構單鏈表(C++)
一. 標頭檔案—linkedlist.h 1 #ifndef _LIKEDLIST_H_ 2 #define _LIKEDLIST_H_ 3 4 #include <iostream> 5 6 template <class T> 7 struc
資料結構三——鏈式儲存結構
● 鏈式儲存結構 特點:用一組任意的儲存單元儲存線性表的資料元素,可以連續也可以不連續,不僅含有資料元素還要有前驅、後繼元素的地址。 &nbs
資料結構---閒心表:鏈式儲存結構
前面說到線性表的順序儲存結構,它的插入和刪除動作需要移動大量元素,費時。 原因:順序儲存結構的線性表,相鄰元素的儲存結構也是鄰居關係,中間沒有空隙,無法快速介入,而刪除的時候回留出空隙,需要彌補。 線性錶鏈式儲存結構定義 資料域(data):儲存資料元素資訊的域 指標
大話資料結構 —— 3.6 線性表的鏈式儲存結構
3.6.1 順序儲存結構不足的解決辦法 C同學:反正要在相鄰元素間留多少空間都是有可能不夠的,那不如乾脆不要考慮相鄰位置這個問題了。哪裡有空位就放在哪裡,此時指標剛好可以派上用場。 每個元素多用一個
資料結構學習筆記——堆疊之鏈式儲存結構(c語言實現)
棧的鏈式儲存結構使用單鏈表實現,同線性表一樣,鏈式儲存結構的堆疊在儲存空間的利用上顯得更加靈活,只要硬體允許一般不會出現溢位的情況。但鏈式棧相對於順序棧稍顯麻煩,若所需堆疊空間確定,順序棧顯得方便一些。關於鏈式和順序式的選擇視具體情況而定。 1.棧的鏈式儲存結構
資料結構之自建演算法庫——二叉樹的鏈式儲存及基本運算
二叉樹的鏈式儲存演算法庫採用程式的多檔案組織形式,包括兩個檔案: 1.標頭檔案:btree.h,包含定義二叉樹的鏈式儲存資料結構的程式碼、巨集定義、要實現演算法的函式的宣告;#ifndef BTREE_H_INCLUDED#define BTREE_H_
大話資料結構九:佇列的鏈式儲存結構(鏈佇列)
1. 鏈佇列的特點: 鏈佇列其實就是單鏈表,只不過它是先進先出的單鏈表,為了實現方便,程式中設定了隊頭(front),隊尾(rear)兩個指標。 2. Java使用連結串列實現佇列: //結點類,包含結點的資料和指向下一個節點的引用 public class N
資料結構棧和佇列(五)棧的順序儲存結構和鏈式儲存結構的實現
一、 實驗目的1. 熟悉棧的特點(先進後出)及棧的抽象類定義;2. 掌握棧的順序儲存結構和鏈式儲存結構的實現;3. 熟悉佇列的特點(先進先出)及佇列的抽象類定義;4. 掌握棧的順序儲存結構和鏈式儲存結構的實現;二、實驗要求1. 複習課本中有關棧和佇列的知識;2. 用C++語言
【資料結構】線性表的鏈式儲存結構--單鏈表
1. 線性表的鏈式儲存結構 鏈式儲存:用一組任意的儲存單元儲存線性表中的資料元素。用這種方法儲存的線性表簡稱線性連結串列。 儲存連結串列中結點的一組任意的儲存單元可以是連續的,也可以是不連續的,甚至是零散分佈在記憶體中的任意位置上的。 連結串列中結點的邏輯順序和物理順序不
(一)線性表的鏈式儲存結構
2.3.1 線性表的鏈式儲存結構——連結串列 連結串列: 1.每個節點中除資料域外,設定了一個指標域,用以指向其後繼節點,這樣構成的連結表稱為線性單向連結串列,簡稱單鏈表。 2.每個節點中除資料域外,設定兩個指標域,分別用以指向其前驅節點和
走進資料結構和演算法(c++版)(3)——線性表的鏈式儲存結構
線性表的鏈式儲存結構 我們知道線性表的順序儲存結構在插入和刪除操作時需要移動大量的資料,他們的時間複雜度為O(n)O(n)。當我們需要經常插入和刪除資料時,順序儲存結構就不適用了,這時我們就需要用到線性表的鏈式儲存結構。 線性表的鏈式儲存結構的特點是
《資料結構和演算法》之棧的鏈式儲存結構
在上篇博文中我已經將棧的順序儲存結構簡單地介紹了一下,也舉了一個進位制轉換的例子,供大家學習參考。這裡將繼續進行棧的有關介紹,本篇博文重點對棧的鏈式儲存結構進行分析。 一,棧的鏈式儲存結構 棧的鏈式儲存結構簡稱棧鏈。棧因為只是棧頂來做插入和刪