系列文章目录:
线性表
线性表就是一种线性结构,它是由 $n$ 个具有相同类型的数据元素组成的有限序列。
线性表的特点:
- 有序性:线性表中的数据元素存在一对一的线性关系,即除了第一个元素外,每个元素都有唯一的前驱元素;除了最后一个元素外,每个元素都有唯一的后继元素。
- 有限性:线性表中包含的数据元素个数是有限的,即线性表的长度是有限的。
线性表可以采用顺序存储结构或链式存储结构来表示。
顺序表
顺序表是一种线性表的顺序存储结构,它使用一组连续的存储单元来存储线性表中的数据元素。
特点
- 顺序表中的数据元素在内存中是连续存储的,即每个元素都存储在相邻的存储单元中。
- 顺序表中的数据元素可以通过下标直接访问,即可以通过下标快速定位到指定的数据元素。
以上是一个顺序表的示意图。
我们要实现的顺序表应该具有功能:
1. 插入元素(增)
2. 删除元素(删)
3. 修改元素(改)
4. 查找元素(查)
实现代码
我自己写了一个顺序表,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #include<iostream> #include <windows.h>
using namespace std;
const int MAXSIZE = 10000; typedef long long ElementType;
struct Seqlist { ElementType list[MAXSIZE]; long long length;
Seqlist() { length = 0; }
int Insert(long long i, ElementType x) { if (i < 0 || i > length) { cout << "插入位置不合法" << endl; return 0; } if (length >= MAXSIZE) { cout << "顺序表已满" << endl; return 0; } for (long long j = length; j > i; j--) list[j] = list[j - 1]; list[i] = x; length++; return 1; }
int Delete(long long i) { if (i < 0 || i >= length) { cout << "删除位置不合法" << endl; return 0; } for (long long j = i; j < length - 1; j++) list[j] = list[j + 1]; length--; return 1; }
long long Get(long long i) { if (i < 0 || i >= length) { cout << "查找位置不合法" << endl; return -1; } return list[i]; }
int Modify(long long i, ElementType x) { if (i < 0 || i >= length) { cout << "修改位置不合法" << endl; return 0; } list[i] = x; return 1; }
bool isEmpty() { return length == 0; }
void Reverse() { for (long long i = 0; i < length / 2; i++) swap(list[i], list[length - i - 1]); }
Seqlist Find(ElementType x) { Seqlist indices; for (long long i = 0; i < length; i++) if (list[i] == x) indices.Push_back(i); return indices; }
int Push_back(ElementType x) { return Insert(length, x); } int Pop_back() { return Delete(length - 1); } int Push_top(ElementType x) { return Insert(0, x); } int Pop_top() { return Delete(0); } };
int main() { SetConsoleOutputCP(CP_UTF8); Seqlist L; L.Push_back(1); L.Push_back(1); for(long long i=2; i<1213; i++) L.Insert(i,L.Get(i-1)+L.Get(i-2)); for(auto i=0; i<10; i++) cout << L.Get(i) << " "; cout << endl; Seqlist F = L.Find(1); for(int i=0; i<F.length; i++) cout << "值 " << i << " 对应的索引为" << F.Get(i) << " "; system("pause"); }
|
链表
相对于顺序表,链表的插入和删除操作更加高效,但是访问链表中的元素需要遍历整个链表。
链表是一种线性表的链式存储结构,它使用一组不连续的存储单元来存储线性表中的数据元素。
特点
- 链表中的数据元素不连续存储,而是通过指针链接在一起。
- 链表中的数据元素可以通过指针访问,但是不能通过下标直接访问。
为了表示每个数据元素 与其后继数据元素 之间的逻辑关系,对于数据元素 来说,除了存储其本身的信息外,还需存储一个指向其后继数据元素的指针。这两部分组成数据元素 的存储映像,称为结点(Node)。
节点包括两个部分:数据域和指针域。数据域用于存储数据元素的信息,指针域用于存储指向后继节点的指针。
n个节点通过指针链接成一个链表,这种链表称为单链表。此外,每个节点还包含一个指针域,用于指向前驱节点,这种链表称为双向链表。如果链表成环,则称为循环链表。
graph LR
%% 核心结构
HEAD((HEAD)) -->|next| Node1
HEAD -.->|prev| NULL_HEAD[/NULL/]
Node1 -->|prev| HEAD
Node1 -->|data| DATA1[Data 1]
Node1 -->|next| Node2
Node2 -->|prev| Node1
Node2 -->|data| DATA2[Data 2]
Node2 -->|next| Node3
Node3 -->|prev| Node2
Node3 -->|data| DATA3[Data 3]
Node3 -->|next| NULL_TAIL[/NULL/]
%% 样式定义
classDef head fill:#1e3a8a,stroke:#bde0fe,color:#fff;
classDef node fill:#1e90ff,stroke:#bde0fe,color:#fff;
classDef data fill:#32CD32,stroke:#fff,color:#000;
classDef null fill:#555,stroke:#fff,color:#fff;
classDef nextPointer stroke:#FFA500,stroke-width:2px;
classDef prevPointer stroke:#00FF00,stroke-width:2px,dashed;
class HEAD head
class Node1,Node2,Node3 node
class DATA1,DATA2,DATA3 data
class NULL_HEAD,NULL_TAIL null
%% 箭头样式
linkStyle 0,3,6,9 stroke:#FFA500,stroke-width:2px
linkStyle 1,4,7,10 stroke:#00FF00,stroke-width:2px,dashed
以上就是双向链表的图示。
- 🔵 蓝色圆角矩形:头节点
HEAD
- 🔷 蓝色矩形:普通节点
- 🟩 绿色区块:数据域
- ⬛ 灰色菱形:NULL标识
实现代码
这里我先写一个单向链表,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| #include<iostream> #include <windows.h>
using namespace std;
const int MAXSIZE = 10000; typedef long long ElementType;
struct Nodelist { ElementType data; struct Nodelist* next; };
Nodelist* init() { Nodelist* head = new Nodelist; head->next = NULL; return head; }
void insertHead(Nodelist* Head, ElementType data) { Nodelist* p = new Nodelist; p->data = data; p->next = Head->next; Head->next = p; }
void insertTail(Nodelist* Tail, ElementType data) { Nodelist* p = new Nodelist; p->data = data; p->next = NULL; Nodelist* q = Tail; while (q->next != NULL) q = q->next; q->next = p; }
void insertNode(Nodelist* Node, ElementType data, int i) { if(Node==NULL) {cout << "链表为空" << endl; return; } Nodelist* p = new Nodelist; Nodelist* q = Node; for(int j=0; j<i; j++) {
if(q->next == NULL) { cout << "插入位置错误" << endl; return; } q = q->next; } p->data = data; p->next = q->next; q->next = p; }
void deleteNode(Nodelist* Node, int i) { Nodelist* p = Node; for(int j=0; j<i; j++) { if(p->next == NULL) { cout << "删除位置错误" << endl; return; } p = p->next; } if(p->next == NULL) {cout << "删除位置错误" << endl; return; } Nodelist* q = p->next; p->next = p->next->next; delete(q); }
int main() { SetConsoleOutputCP(CP_UTF8); Nodelist* L = init(); for(int i=1; i<=5; i++) insertHead(L, i); for(int i=1; i<=5; i++) insertTail(L, i); Nodelist* temp = L; while(temp->next != NULL) { cout << temp->next->data << " "; temp = temp->next; } cout << endl << "-----------------" << endl; insertNode(L, 100, 5); cout << "在下标5处插入100" << endl; temp = L; while(temp->next != NULL) { cout << temp->next->data << " "; temp = temp->next; } cout << endl << "-----------------" << endl; deleteNode(L, 5); cout << "删除下标5处的节点" << endl; temp = L; while(temp->next != NULL) { cout << temp->next->data << " "; temp = temp->next; } system("pause"); }
|