第一章 基本緒論
1.2 基本概念和術語
- 數據(Data):客觀事物的符號表示,所有能夠輸入計算中並被計算機處理的符號的總稱。
- 數據元素(Data Element):數據的基本單位,在計算機中作爲一個整體進行考慮和處理。
- 數據項(Data Item): 是組成數據元素的、有獨立含義的、不可再分的最小單位。
- 數據對象(Data Object): 是性質相同的數據元素的集合,是數據的子集。
- 數據結構(Data Structure): 相互之間存在一種或特定多種關係的數據元素的集合。"結構"就是數據元素之間存在的關係。
- 邏輯結構:從邏輯上描述數據,它與數據的存儲無關,獨立於計算機。2個要素:數據元素和關係
- 集合結構:屬於同一集合的關係。
- 線性結構:一對一的關係。
- 樹結構:一對多的關係。
- 圖結構:多對多的關係。
-
存儲結構(物理結構):數據對象在計算機中的存儲。即要存儲數據元素的數據,也要存儲元素之間的邏輯關係。
-
順序存儲結構:藉助元素在存儲器上的相對位置來表示元素之間的關係。要求一片連續的空間。
-
鏈式存儲結構:無需一片連續的空間,但是爲了表示元素之間的關係,需要添加一個指針字段,保存後繼元素的存儲地址。
-
-
數據類型(Data Type):是一個值的集合和定義在這個值集上的一組操作的總稱。
-
抽象數據類型(Abstract Data Type, ADT): 一般由用戶定義,表示應用問題的數學模型,以及在這個模型上的一組操作的總稱,包含數據對象、數據關係、基本關係。
1.4算法和算法分析
- 算法(Algorithm):爲了解決某類問題而規定的一個有限長的操作序列。
- 有窮性: 必須在執行有窮步後停止,且每一步都必須在有限時間內完成。
- 確定性: 每種情況下所執行的操作必須是確定的。
- 可行性:算法中的所有操作都可以通過已經實現的基本操作執行有限次完成。
- 輸入:0個或多個輸入。
- 輸出:一個或多個輸出。
- 評估算法優劣的基本標準
- 正確性
- 可讀性
- 健壯性
- 高效性
- 時間複雜度(Time Complexity): 算法時間的量度。
- 空間複雜度(Space Complexity):算法存儲空間的量度。指算法實現時需要的輔助空間,與輸入數據所需的存儲量無關。
第二章 線性表
順序存儲
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXSIZE 1005
#define OK 1
#define ERROR 0
typedef int Status;
using namespace std;
struct Book{
char no[30];
char name[30];
double price;
bool operator == (const Book &w) const {
if (!strcmp(no, w.no)) return true;
return false;
}
};
struct List {
Book* elem;
int lenth;
};
//初始化線性表
Status initList(List &list) {
list.elem = new Book[MAXSIZE];
if (!list.elem) exit(0); //創建失敗
list.lenth = 0;
return OK;
}
//獲取線性表元素
Status getElem(List &list, int i, Book &elem) {
if (i < 1 || i > list.lenth) return ERROR;
elem = list.elem[i - 1];
return OK;
}
//獲取某個元素在線性表中的位置 不存在返回0
int locateElem(List &list, Book &elem) {
for (int i = 0; i < list.lenth; i++) {
if (elem == list.elem[i]) return i + 1;
}
return 0;
}
//添加元素
Status insertElem(List &list, Book &elem) {
if (list.lenth == MAXSIZE) return ERROR;
list.elem[list.lenth++] = elem;
return OK;
}
//添加元素通過位置
Status insertElem(List &list, int i, Book &elem) {
if (i < 1 || i > list.lenth + 1) return ERROR;
for (int j = list.lenth - 1; j >= i - 1; j--) {
list.elem[j + 1] = list.elem[j];
}
list.elem[i - 1] = elem;
list.lenth++;
return OK;
}
//刪除指定位置的元素
Status deleteElem(List &list, int i) {
if (i < 1 || i > list.lenth) return ERROR;
for (int j = i - 1; j < list.lenth - 1; j++) list.elem[j] = list.elem[j + 1];
list.lenth--;
return OK;
}
void output(Book &elem) {
printf("no:%s name:%s price: %lf\n", elem.no, elem.name, elem.price);
}
List list;
int main() {
initList(list);
//添加元素
Book books[100];
for (int i = 1; i <= 3; i++) {
Book book;
scanf("%s%s%lf", book.no, book.name, &book.price);
insertElem(list, i, book);
}
for (int i = 0; i < list.lenth; i++) output(list.elem[i]);
return 0;
}
鏈式存儲
-
首元結點:是指鏈表中存儲的第一元素結點。
-
頭結點:是首元結點之前設置的一個結點,其指針域指向首元結點。
-
鏈表是非隨機存取的結構,要取得某個元素,必須從頭指針出發進行尋找,也可稱爲順序存取的結構。
-
ASL(Average Search Length) = n-1 / 2 (0, 1, 2,…,n-1)
單鏈表
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXSIZE 1005
#define OK 1
#define ERROR 0
typedef int Status;
using namespace std;
struct Book{
string no;
string name;
double price;
bool operator == (const Book &w) const {
if (no == w.no) return true; return false;
}
};
typedef struct Node {
Book elem;
Node *next;
}Node, *List;
//初始化頭節點
Status initList(List &L) {
L = new Node();
L->next = NULL;
return OK;
}
//獲取鏈表中的元素
Status getElem(List &L, int i, Book &e) {
Node *p = L->next;
int j = 1; //代表標號
while (p && j < i) {
p = p->next; j++;
}
if (!p || j > i) return ERROR;
e = p->elem;
return OK;
}
//單鏈表的插入, 插入位置爲i 即ai-1 與ai之間 合法區間[1,n+1]
Status insertElem(List &L, int i, Book &e) {
Node *p = L; //初始從0開始
int j = 0;
while (p && j < i - 1) { //在i-1的位置停下
p = p->next; j++;
}
if (!p || j > i - 1) return ERROR;
Node *s = new Node();
s->elem = e;
//執行鏈接操作
s->next = p->next;
p->next = s;
return OK;
}
//輸出鏈表中的元素
void output(List &L) {
Node *p = L;
while (p->next) {
p = p->next;
cout << p->elem.no << " " << p->elem.name << " " << p->elem.price << endl;
}
}
//按值查找 查找失敗返回NULL
Node *locateElem(List &L, Book &e) {
Node *p = L->next;
while (p && !(p->elem == e)) p = p->next;
return p;
}
//刪除指定位置的結點 [1, n]
Status deleteElem(List &L, int i) {
Node *p = L;
int j = 0;
while (p && j < i - 1) {
p = p->next; j++;
}
//注意必須後面結點存在
if (!(p->next) || j > i - 1) return ERROR;
Node *s = p->next;
delete(s); //釋放結點
p->next = p->next->next;
return OK;
}
//創建鏈表,並添加n個元素--前插法
void createListHead(List &L, int n) {
L = new Node();
L->next = NULL;
for (int i = 1; i <= n; i++) {
Node *p = new Node();
cin >> p->elem.no >> p->elem.name >> p->elem.price;
p->next = L->next;
L->next = p;
}
}
//創建鏈表,並添加n個元素--後插法
void createListRear(List &L, int n) {
L = new Node();
L->next = NULL;
Node *r = L;
for (int i = 1; i <= n; i++) {
Node *p = new Node();
cin >> p->elem.no >> p->elem.name >> p->elem.price;
r->next = p;
p->next = NULL;
r = p; //新的節點成爲尾結點
}
}
List L;
int main() {
// initList(L); //初始化
createListRear(L, 3);
output(L);
return 0;
}