数据结构 第二章 线性表
概念:
具有相同数据类型的数据元素的有限序列。
表示:L = (A1,A2,A3,...AN),N为表长 其中 A1称为表头,AN为表尾, A2是A3的前驱,A3是A2的后继。
链表的基本操作: 创建 销毁 判空 增删改查
函数名称及作用,实际可以用其他名称,这里只作为举例;
【创建】InitList(&L):初始化表,构造一个空的线性表,分配内存空间。
【销毁】DestroyList(&L): 销毁线性表,并释放线性表所占的内存空间。
【增】InsertList(&L, i,e):在表中的第 i个位置上插入指定的元素e。
【删】DeleteList(&L, i,&e):删除表L中第i 个位置的元素,并且将删除元素的值赋值给e。
【改】SetList(&L, i,e):在表中的第 i个位置修改为元素 e,一般不使用。
【查】LocateElem(L,i,e):按值查找。
【查】GetElem(L,i):按索引查找。
物理结构划分:
【顺序表】
以数组的形式存储。
指针步长:
void test_array_202101121057()
{
int a[5][6];
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 6; j++)
{
a[i][j] = i * 10 + j;
}
}
int(*p)[6];
p = a;
int* p1 = a[1];
int* p2 = &a[1][0];
printf("p1 = %d *(p1+1)=%d\n", p1, *(p1 + 1));
printf("p2 = %d *(p2+1)=%d\n", p2, *(p2 + 1));
printf("(a+%d)[%d][%d]=%d\n", 2,0,2,(a+2)[0][2]); // a的步长为跳转一行
}
【动态链表】=【单链表】+【双链表】
以指针的形式动态建立数据的存储单元。
链表插入方法:头插法、尾插法
【头插则是将新节点链接到链表的头结点的后面】
以单链表为例:
current->next=head->next;//新节点的指针域指向*头结点的指针域原来指向的节点(即第一个节点)
head->next=current;//头节点的指针域指向新节点,新节点变为第一个节点。
【尾插则是将新节点链接到链表的尾部】
以单链表为例:
tail->next=current;//原链表尾节点指针域指向新节点
tail=current;//尾指针指向新链接的新节点,新节点变链表的尾节点(尾指针始终指向尾节点)
【静态链表】
以结构体数组的形式存在。
特点:
节省内存
不支持随机存储,使用比较少
应用:
FAT(文件配置表)
【循环链表】
表尾指向表头,表头指向表尾
顺序表与链表的比较:
顺序表,随机存取效率高,存储密度高,但是扩容差 ,;中间插入\删除数据,可能移动大量数据,效率低。
链表:冗余信息较多,存储密度低,随机存储效率低,扩容性好;中间插入/删除 数据,效率高。
【代码实现】
Dlist.h
#pragma once using DoubleNode = struct _dNode { int data; struct _dNode* pProir; struct _dNode* pNext; }; // 双向链表 class Dlist { public: // init 放到构造函数中 Dlist(); // destroy 放到析构函数中 virtual ~Dlist(); // 前插数据 int InsertHead(int value); // 后插数据 int InsertEnd(int value); // 删除元素 int erase(int index); // 设定元素值 int setValue(int index, int value); // 查找从Index 后面值为value的元素的索引 int LocateElem(int index, int value); // 查找从Index 的值 int GetElemValue(int index, int& value); // 判断链表是否为空 bool IsEmpty(); protected: // 取得下标为 index 的元素 DoubleNode* getElem(int index); private: DoubleNode* pHead;// 表头 DoubleNode* pTail;// 表尾 int num;// 元素的个数 };
Dlist.cpp
#include "Dlist.h" Dlist::Dlist() { pHead = new DoubleNode{0, nullptr, nullptr};// 表头 pTail = new DoubleNode{0, nullptr, nullptr};// 表尾 pHead->pNext = pTail; pTail->pProir = pHead; num = 0;// 元素的个数 } Dlist::~Dlist() { while (pHead->pNext !=nullptr) { DoubleNode* Elem = pHead->pNext; pHead->pNext = Elem->pNext; delete Elem; } delete pHead; } // 前插数据 int Dlist::InsertHead(int value) { DoubleNode* Elem = new DoubleNode{value, nullptr, nullptr}; num++; Elem->pNext = pHead->pNext; Elem->pProir = pHead; pHead->pNext = Elem; Elem->pNext->pProir = Elem; return 0; } // 后插数据 int Dlist::InsertEnd(int value) { DoubleNode* Elem = new DoubleNode{value, nullptr, nullptr}; num++; Elem->pProir = pTail->pProir; Elem->pNext = pTail; Elem->pProir->pNext = Elem; pTail->pProir = Elem; return 0; } // 取得下标为 index 的元素 DoubleNode* Dlist::getElem(int index) { if ((index >= num) || nullptr == pHead) { return nullptr; } // 第0号元素 DoubleNode* Elem = pHead->pNext; // 找到指定元素 while (index >= 1) { Elem = Elem->pNext; index--; } return Elem; } // 删除元素 int Dlist::erase(int index) { DoubleNode* Elem = getElem(index); if (nullptr == Elem) { return -1; } // 修改指针链 Elem->pProir->pNext = Elem->pNext; Elem->pNext->pProir = Elem->pProir; // 删除结点 delete Elem; // 计数减一 num--; return 0; } // 设定元素值 int Dlist::setValue(int index, int value) { DoubleNode* Elem = getElem(index); if (nullptr == Elem) { return -1; } Elem->data = value; return 0; } // 查找从Index 后面值为value的元素的索引 int Dlist::LocateElem(int index, int value) { DoubleNode* Elem = getElem(index); if (nullptr == Elem) { return -1; } int retIndex = index; do { if (Elem->data == value) { break; } retIndex++; } while (nullptr != (Elem = Elem->pNext)); if (retIndex == num) { retIndex = -1; } // 函数值返回 return retIndex; } // 查找从Index 的值 int Dlist::GetElemValue(int index,int& value) { DoubleNode* Elem = getElem(index); if (nullptr == Elem) { return -1; } value = Elem->data; return 0; } // 判断链表是否为空 bool Dlist::IsEmpty() { return num = 0 ? true : false; }
测试函数:
void test_Dlist_20210113() { int a[5] = {1, 2, 3, 4, 5}; Dlist* dlist = new Dlist(); for (int i = 0; i < 5; i++) { dlist->InsertHead(a[i]); } for (int i = 0; i < 5; i++) { int v = 0; dlist->GetElemValue(i, v); cout << v << " "; } delete dlist; cout << endl; dlist = new Dlist(); for (int i = 0; i < 5; i++) { dlist->InsertEnd(a[i]); } for (int i = 0; i < 5; i++) { int v = 0; dlist->GetElemValue(i, v); cout << v << " "; } delete dlist; cout << endl; dlist = new Dlist(); for (int i = 0; i < 5; i++) { dlist->InsertHead(a[i]); } dlist->erase(2); for (int i = 0; i < 5; i++) { int v = 0; if (0 != dlist->GetElemValue(i, v)) { continue; } cout << v << " "; } cout << endl; bool isempty = dlist->IsEmpty(); if (isempty) { cout << "空 "; } else { cout << "非空 "; } cout << endl; delete dlist; dlist = new Dlist(); for (int i = 0; i < 5; i++) { dlist->InsertHead(a[i]); } for (int i = 0; i < 5; i++) { dlist->erase(0); } isempty = dlist->IsEmpty(); if (isempty) { cout << "空 "; } else { cout << "非空 "; } cout << endl; dlist->InsertEnd(6); dlist->InsertEnd(7); dlist->InsertEnd(8); dlist->InsertEnd(9); for (int i = 0; i < 5; i++) { int v = 0; if (0 != dlist->GetElemValue(i, v)) { continue; } cout << v << " "; } cout << endl; isempty = dlist->IsEmpty(); if (isempty) { cout << "空 "; } else { cout << "非空 "; } cout << endl; delete dlist; }
【内容总结】
结束