数据结构(Course)2:线性表

内部结点唯一的前驱和后继,表头 只有后继,表尾只有前驱。

1、线性结构

线性表:顺序表(数组)、链表

:插入和删除都限制在表的同一端进行(后入先出)

队列:插入在一端,删除在另一端(先进先出)

//线性表类模板如下,是顺序表类和链表类的基类,用虚函数virtual
template <class T>
//value的类型是T
class LinearList
{
	virtual void clear() const=0;//置空线性表
	virtual bool isEmpty() const=0;//线性表为空时,返回true
	//增
	virtual bool append(const T value)=0;//表尾添加一个元素value
	virtual bool insert(const int p, const T value)=0;//位置p上插入元素value
	//删
	virtual bool delete(const int p)=0;//删除位置p上元素
	//改
	virtual bool setValue(cosnt int p, const T value)=0;//用value修改位置p的元素值
	//查
       virtual bool getPos(int& p, const T value) const=0;//查找元素为value的元素并返回其位置

       virtual bool getValue(const int p, T& value) const=0;//把位置p元素返回变量value
       virtual bool find(const int p, T& value) const = 0;//在x中返回表中下标为i的元素。若存在则返回true
};

2、顺序表

//顺序表,继承线性表
template <class T>
class arrList :public LinearList<T>
{
private:
	T* alist;//指向顺序表的指针
	int maxSize;//顺序表最大长度
	int curLen;//当前长度
	int position;//当前位置
public:
	//构造函数创建新表,设置表实例的最大长度
	arrList(const int size)
	{
		maxSize = size;
		alist = new T[maxSize];//new一个数组空间
		curLen = position = 0;
	}
	//析构函数
	~arrList()
	{
		delete[] alist;
	}
};

查找:

//在value中返回表中下标为p的元素
virtual bool find(const int p, T& value) const
{
	if (p<0 || p>this->n)
	{
		cout << "out of bounds" << endl;
		return false;
	}
	value = islist[p];
	return true;
}

插入:

template <class T>
//定义插入
//p为新元素value的插入位置,插入成功则返回true
//curLen表示当前总长度
bool arrList<T>::insert(const int p, const T value)
{
	int i;
	if (curLen >= maxSize)//溢出
	{
		return false;
	}
	if (p<0 || p>curLen)//插入位置是否合法
	{
		return false;
	}
        //数组需要遍历操作,从表尾向上走
	for (i = curLen; i > p; i--)
	{
		alist[i] = alist[i - 1];//从表尾curLen-1起向后移动直到p
	}
		alist[p] = value;//位置p处插入新元素
		curLen++;//表的实际长度+1
}

删除:

template <class T>
//定义删除
//p为即将删除元素的位置,插入成功则返回true
//curLen表示当前总长度
bool arrList<T>::insert(const int p, const T value)
{
	int i;
	if (curLen <= 0)//是否为空
	{
		return false;
	}
	if (p<0 || p>curLen-1)//插入位置是否合法
	{
		return false;
	}
        //遍历,从当前位置开始向表尾
	for (i = p; i <curLen-1; i++)
	{
		alist[i] = alist[i + 1];//从p开始每个元素左移直到curLen
	}
		curLen--;//表的实际长度-1
}

线性表的顺序表示是用一组地址连续的存储单元依次存储线性表中的元素。这样,逻辑上相邻的元素在物理上也相邻。顺序表是一种随机存取结构,但是插入和删除时效率较低,时间主要消耗在移动元素上。

插入移动n-i;删除移动n-i-1;

时间复杂度为O(n)

3、链表

哪里有空位就到哪里,大小不固定。

p->data数据元素;p->next指针

//单链表类定义
template <class T>
//结点类型
class Node
{
public:
	T data;//节点元素内容
	Node<T> *next;//指向后继节点的指针
        //构造函数
	Node(const T info, cosnt Node<T>* netvalue = NULL)
	{
		data = info;
		next = nextvalue;
	}
};

//单链表类继承线性表
class SingleList :public LinearList < T >
{
	private:
             Node<T>* head;
};
//构造函数
SingleList() 
{
    head = new Node<T>;
    head->next = NULL;
    this->n = 0;
}
//析构函数
~SingleList() 
{
    Node<T> *p;
    while (head != NULL) 
   {
        p = head;
        head = head->next;
        delete (p);
    }
}

1、查找单链表中第i个节点

template <typename T>
bool SingleList<T>::Find(int i, T &x) const {
    if (i < -1 || i > this->n - 1) {
        cout<<"Out of bounds"<<endl;
        return false;
    }
    Node<T>* p = head;
    for (int j = 0; j <= i; ++j) {
        p = p->next;
    }
    x = p->element;
    return true;
}

2、单链表的插入

创建新节点->新节点指向右边的节点->左边节点指向新节点

s->data=e; s->next=p->next; p->next=s;

template <typename T>
bool SingleList<T>::Insert(int i, T x) {
    if (i < -1 || i > this->n - 1) {
        cout<<"Out of bounds"<<endl;
        return false;
    }
    Node<T>* p = head;
    for (int j = 0; j <= i ; ++j) {
        p = p->next;
    }
    Node<T> *newNode = new Node<T>;
    newNode->element = x;
    newNode->next = p->next;
    p->next = newNode;
    this->n++;
    return true;
}

3、单链表的删除

p->next=p->next->next

template <typename T>
bool SingleList<T>::Delete(int i) {
    if (i < -1 || i > this->n - 1) {
        cout<<"Out of bounds"<<endl;
        return false;
    }
    Node<T> *p = head;
    for (int j = 0; j < i; ++j) {
        p = p->next;
    }
    Node<T> *tmp = p->next;
    p->next = p->next->next;
    delete (tmp);
    this->n--;
    return true;
}

运算的分析:从第一个点开始

p=head;

while(没有到达)p=p->next

双链表插入(注意顺序)

注意:

头指针处理

非循环链表表尾节点的指针保持为NULL

循环链表结尾的指针回指头结点

插入删除少用顺序表,动态结点变化插入删除多用链表

猜你喜欢

转载自blog.csdn.net/try_again_later/article/details/81199004
今日推荐