数据结构线性表的教程:
一、线性表的基本知识:
- 存在唯一的一个被称做第一个
- 存在唯一的一个被称作最后一个
- 除第一个之外集合中的每个元素只有一个前驱
- 除最后一个之外,集合中的每个元素均只有一个后继
5 特点:线性表既有物理上的结构也可以有逻辑上的结构
二、线性表的操作
1.线性表的初始化
2.线性表的遍历
3.线性表插入元素
4.线性表删除元素
// 基本操作如下 其实最主要的是思想 不是代码的实现 ,首先带着一种为什么这样操作的思想来看代码 这样会一步步理解 每到一步就应该想到,这步有什么作用,为什么实现这一步。链表的实现其实就是增删改查,首先大致浏览一步函数 有多少个函数,设计多少函数,函数怎么设计,设计之后函数怎么调用 函数怎么传参!
#ifndef LIST_H // 防止其中的数据成员和方法重复 这个文件我命名为 List.h 这样留下面的函数引用
#define LIST_H
class List // 添加数据成员
{
public:
List(int size); // 初始化线性表
~List(); // 析构函数相当与c当中的销毁线性表
void ClearList(); // 清空线性表就是释放线性内存
bool ListEmpty(); // 判断线性表为空的操作
int ListLength(); // 也就是获取线性表的长度将当前线性表的长度作为返回值return 回去 返回的内容实际是m_iLength的值
bool GetElem(int i,int *e); // 获取当前的元素
int LocateElem(int *e);// 定位一个元素
bool PriorElem(int *currentElem,int *preElem);
bool NextElem(int *currentElem,int *nextElem);
void ListTraverse();// 遍历线性表
bool ListInsert(int i,int *e);
bool ListDelete(int i,int *e);
private:
int *m_pList; // 用这个指针指向一块内存空间,用这个内存存储线性表
int m_iSize; // 获取线性表的长度
int m_iLength; //
};
#endif
// 在本次代码实现中我采用了3个程序文件实现:
#include"List.h" // 引用上面的类 这个文件我命名为 List.cpp
#include<iostream>
using namespace std;
List::List(int size) // 构造函数
{
m_iSize=size; // 用户所指向的容量保存到数据成员当中
m_pList = new int [m_iSize] ; //分配内存
m_iLength = 0 ;// 初始状态下 为0 //当前的线性表中究竟存放了几个线性表的元素
}
List::~List() // 析构函数 在析构函数中最主要的功能就是讲构造函数中申请的内存释放掉
{
delete []m_pList;
m_pList=NULL;
}
void List::ClearList(){
// 实现清空的操作就是让ilength的值为0
m_iLength=0;
}
bool List::ListEmpty(){ // 判断线性表是否为空
if (m_iLength==0)
{
return true;
}
else{
return false;
}
//return m_iLength==0?true:false;
}
int List::ListLength()
{
return m_iLength;
}
bool List::GetElem(int i,int *e)
{ //获取指定的元素
if(i<0||i>m_iSize)
{//判断一下是否有这个元素 在这种情况下就没有办法取到指定的元素
return false;
}
// 否则就把这个值传递给 e
*e=m_pList[i];
return true;
}
int List::LocateElem(int *e)
{ // 寻找第一个满足e的数据元素的位序// 定位元素 也就是查找元素 需要用到for循环遍历的操作
for(int i=0;i<m_iLength;i++)
{
if(m_pList[i]==*e)
{
return i;
}
}
return -1; // 没有找到
}
bool List::PriorElem(int *currentElem,int *preElem)
{ //寻找前驱和后继
int temp=LocateElem(currentElem); // 用一个返回值 存储找到的前驱的元素
if(temp==-1){ // 如果temp==-1 说明没有找到
return false;
}
else
{
if(temp==0){ // 则就在头位置 说明没有前驱
return false;
}
else
{ //既不等于零也不等于-1 则找到这个前驱
*preElem=m_pList[temp-1]; //将所找到的元素赋值给前驱
return true;
}
}
}
void List::ListTraverse()
{
for (int i=0;i<m_iLength;i++){ // i 小于当前表中的个数
cout<<m_pList[i]<<" ";
}
}
bool List::NextElem(int *currentElem,int *nextElem){
int temp=LocateElem(currentElem); // 用一个返回值 存储找到的前驱的元素
if(temp==-1)
{ // 如果temp==-1 说明没有找到
return false;
}
else
{
if(temp==m_iLength-1){ // 则就在尾位置 说明没有后继
return false;
}
else { //既不等于零也不等于-1 则找到这个前驱
*nextElem=m_pList[temp+1]; //将所找到的元素作为后继元素
return true;
}
}
}
bool List::ListInsert(int i,int *e){ //插入位置 后面的元素 需要依次往后移
// 需要增加一个判断条件
if(i<0||i>m_iLength){
return false;
}
for(int k=m_iLength-1;k>=i;k--){ // k从最后一个元素操作不停的做k-- 一直到最后一个元素都往后移一个位置
m_pList[k+1]=m_pList[k]; // 先移动再插入
}
m_pList[i]=*e;
m_iLength++;// 记录当插入到尾部 不进循环不需要移动位置 但是线性表的长度需要加一 ,并且记录当前线性表中已有的元素的个数
return true;
}
bool List::ListDelete(int i,int *e){
if(i<0||i>=m_iLength){ // 如果等于可以那么下面的删除不了任何元素
return false;
}
*e=m_pList[i];// 将i位置上的元素先拷贝出来
for(int k=i+1;k<m_iLength;k++){ // 从当前的位置把后继的元素都往前移动
m_pList[k-1]=m_pList[k];
}
m_iLength--;
return true;
}
// 接下来我需要用的就是在main函数中调用我的方法和数据: 下面的文件我定义为 demo.cpp
#include<stdlib.h>
#include "List.cpp"
int main(void){
int e1=3;
int temp2; // 用于前驱元素存放
int temp3; // 用于后继元素的存放
int temp;// 定义临时变量 用它来去除删除掉的值
int temp1; // 用于查找元素
List *list1 = new List(10); // 调用构造函数传入一个容量
// list1->ListInsert(0,&e1);
for(int i=0;i<10;i++)
{ int j;
scanf("%d",&j);
list1->ListInsert(i,&j);
}
cout<<endl;
cout<<"这是删除前的元素:"<<endl;
list1->ListTraverse();
cout<<"没有删除元素之前线性表长度Length:"<<list1->ListLength()<<endl;
list1->ListDelete(2,&temp); // 删除指定的元素 记住这里面是指针 只需要知道删除的位置即可
cout<<endl<<"这是删除后的元素:"<<endl;
list1->ListTraverse();
cout <<endl<<"这是删除的位置的元素:"<<endl<<temp<<endl;
// if(!list1->ListEmpty()) // 在没有清空线性表时候 验证是否为空
// {
// cout<<"not empty"<<endl;
// }
// list1->ClearList(); //清空线性表
// if(list1->ListEmpty()) // 清空之后验证了
// {
// cout<<"empty"<<endl;
// }
cout<<"删除元素之后线性表长度Length:"<<list1->ListLength()<<endl;
cout<<list1->GetElem(4,&temp1)<<endl;
cout<<temp1<<endl;
list1->LocateElem(&temp1); // 调用指定位置的函数
cout<<endl;
list1->PriorElem(&temp1,&temp2);
list1->NextElem(&temp1,&temp3);
cout<<"取到我指定删除的元素的前驱"<<temp2<<endl;
cout<<"取到我指定删除的元素的后继"<<temp3<<endl;
delete list1;
system("pause");
return 0;
}