数据结构——线性表
2016-11-24 19:45
211 查看
数据结构————线性表
(一)顺序表
1.类声明:template <class T>
class LinearList {
private:
int MaxSize ; // 顺序表的最大长度
int length ; // 顺序表的实际长度
T *element ; // 存储顺序表的数组
public:
LinearList ( int MaxListSize = 10 )
2.插入算法:(时间复杂性O(N))
3.查找算法:
4.删除算法 (时间复杂性O(N))
线性表的顺序存储结构
优点:空间利用率高,简单、易于实现,可以随机访问表中任一元素,存取速度快。
缺点:插入和删除结点,要调整一批结点的地址。
由于线性表中元素的数目可以改变,因此定义数组时要定义合适大小的数组
(二)单链表
1.结点定义:#include <stdlib.h>
/* 单链表结点SLNode的类定义 */
template <class T>
class SLNode
{
public:
// 数据域
T data;// 指针域
SLNode<T> *next;
SLNode(SLNode* nextNode=NULL)// 构造函数
{
next=nextNode;
};
SLNode(const T &item, SLNode* nextNode=NULL)
{
data=item;
next=nextNode;
}
};
2.类定义:template < class T >
class SLList{
private:
SLNode<T> *head ; // 表头指针
public:
SLList ( void ) { head = new SLNode<T>() };
// 构造函数,构造一个只有哨位结点的空表
SLList ( T & item ) ;// 构造函数
~SLList ( void ) ; // 析构函数
bool IsEmpty ( void ) const { return headnext = = NULL ; } ; // 判断链表是否为空
int length ( void ) const ; // 返回表的长度
bool Find ( int k, T & item ) const ; /*存取:将链表中第k个结点的字段值赋给item*/
int Search ( const T & item ) const ; /*查找:在链表中查找字段值为item的结点并返回其表中位置*/
void Delete ( int k, T & item ) ; /* 删除:删除链表中第k个结点并将其字段值赋给item*/
void Insert ( int k, const T & item ) ; /* 插入:在链表中第k个结点后插入字段值为item的结点*/
};
3.查找算法: 最好情况时间复杂度为O(1),最坏情况和平均情况下时间复杂度为O(n)
// 令当前指针指向链表中第k个结点,并将该结点值data返回给item
bool Find(int k, T &item)
{
if(k<1||IsEmpty())
{
cout<<"Invalid number or empty list!";
return false;
}
currptr=head;
for(int i=1; i<=k; i++)
currptr=currptr->next;
item=currptr->data;
return true;
};
4.删除算法:
5.插入算法:
1.
2. 判断空表的的条件: next(head) == head
(四)双向链表
1.定义:指链表中任一结点P都是由data域、左指针域left和右指针域right构成的,左指针域和右指针域分别存放P的左右两边相邻结点的地址信息,链表中表头结点的left指针和表尾结点的right指针均为NULL. 指针head和tail分别指向双向链表的头结点和尾结点,双向链表也被称为双重链表。
2.结构定义:双向链表结点(Double-Linked List Node)DLNode的结构定义
template < class T >
Struct DLNode{
T data;
DLNode<T> *left, *right ;
DLNode ( ) { left = right = NULL ; } ; // 构造函数
DLNode ( const T& item, SLNode * L = NULL, SLNode * R = NULL )
{ data = item ; left = L; right = R ; } // 构造函数
};
3.插入操作:
// 在当前结点后插入
void Insert(const T& item)
{
if(IsEmpty())
{
tail=head->right=new DLNode<T>(item, head, NULL);
size++;
return;
}
DLNode *p=new DLNode<T>(item, currptr, currptr->right);
currptr->right->left=p;
currptr->right=p;
size++;
// 若currptr是表尾,令表尾指针指向新插入结点
if(currptr==tail)
tail=p;
};
// 在表尾插入结点
void InsertFromTail(const T &item)
{
tail=tail->right=new DLNode<T>(item, tail, NULL);
size++;
};
// 在哨位结点后插入
void InsertFromHead(const T &item)
{
if(IsEmpty())
{
tail=head->right=new DLNode<T>(item, head, NULL);
size++;
return;
}
DLNode *p=new DLNode<T>(item, head, head->right);
head->right->left=p;
head->right=p;
size++;
};
4.删除节点: // 删除操作:删除指定结点并将其data值返回给变量de_item
// 删除哨位结点后的第一个真正表结点
bool DeleteFromHead(T &de_item)
{
if(IsEmpty())
{
cout<<"Empty list!";
return false;
}
DLNode<T> *temp=head->ri
9e9b
ght;
head->right=temp->right;
size--;
de_item=temp->data;
// 若原表中除了哨位结点外只有一个表结点
if(temp==tail)
tail=head;
delete temp;
return true;
};
// 删除表尾结点
bool DeleteFromTail(T &de_item)
{
if(IsEmpty())
{
cout<<"Empty list!";
return false;
}
SetEnd();
// 令当前指针指向表尾结点的前趋结点
Prev();
de_item=tail->data;
currptr->right=NULL;
size--;
delete tail;
tail=currptr;
return true;
};
//删除当前结点的右结点
bool Delete(T &de_item)
{
if(IsEmpty()||currptr->right==NULL)
return false;
DLNode<T>*temp=currptr->right;
de_item=temp->data;
if(temp==tail)
tail=currtpr;
else
temp->right->left=currptr;
currptr->right=temp->right;
delete temp;
size--;
return true;
};
(一)顺序表
1.类声明:template <class T>
class LinearList {
private:
int MaxSize ; // 顺序表的最大长度
int length ; // 顺序表的实际长度
T *element ; // 存储顺序表的数组
public:
LinearList ( int MaxListSize = 10 )
{ MaxSize=MaxListSize; // 申请规模为MaxSize的数组空间 element=new T[MaxSize]; // 初始时没有真正表结点, 故表长度为0 length=0; }; // 构造函数,最大长度默认为10 ~LinearList () { delete [] element ; } // 析构函数 bool IsEmpty () const { return length = = 0 ; } // 判断表是否为空 bool IsFull () const { return length = = MaxSize ; } // 判断表是否为满 int Length () const { return length ; } // 返回表的长度 bool Find ( int k, T & item ) const ; //存取:将下标为k的结点的字段值赋给item int Search ( const T & item ) const ; //查找:在表中查找字段值为item的结点并返回其下标 void Delete ( int k, T & item ) ; // 删除:删除下标为k的结点并将其字段值赋给item void Insert ( int k, const T & item ) ; // 插入:在下标为k的结点后插入字段值为item的结点 } ;
2.插入算法:(时间复杂性O(N))
// 插入: 在第k个结点后插入字段值为item的结点 void Insert(int k, const T& item) { // 若表已满无法插入新结点 if(IsFull()) { cout<<"The list is full!"<<endl; exit(1); } // 若第k个结点不存在 if(k<0||k>length) { cout<<"The node does not exist!"<<endl; exit(1); } // 从第k+1个结点开始, 所有结点向后移动一个位置 for (int i=length; i>k; i--) element[i]=element[i-1]; element[k]=item; length++; return; };
3.查找算法:
//查找: 在表中查找字段值为item的结点并返回其所在位置; 若表中没有item, 则返回0 int Search(const T &item) const { for(int i=0; i<length; i++) { if(element[i]==item) return ++i; } return 0; };
4.删除算法 (时间复杂性O(N))
// 删除: 删除第k个结点并将其字段值赋给item void Delete(int k, T &item) { // 若找到第k个元素, 则将其后面所有结点均向前移动一个位置 if(Find(k, item)) { for(int i=k; i<length; i++) element[i-1]=element[i]; // 表长度相应减1 length--; return; } // 否则出错退出 cout<<"The list is full!"<<endl; exit(1); };
线性表的顺序存储结构
优点:空间利用率高,简单、易于实现,可以随机访问表中任一元素,存取速度快。
缺点:插入和删除结点,要调整一批结点的地址。
由于线性表中元素的数目可以改变,因此定义数组时要定义合适大小的数组
(二)单链表
1.结点定义:#include <stdlib.h>
/* 单链表结点SLNode的类定义 */
template <class T>
class SLNode
{
public:
// 数据域
T data;// 指针域
SLNode<T> *next;
SLNode(SLNode* nextNode=NULL)// 构造函数
{
next=nextNode;
};
SLNode(const T &item, SLNode* nextNode=NULL)
{
data=item;
next=nextNode;
}
};
2.类定义:template < class T >
class SLList{
private:
SLNode<T> *head ; // 表头指针
public:
SLList ( void ) { head = new SLNode<T>() };
// 构造函数,构造一个只有哨位结点的空表
SLList ( T & item ) ;// 构造函数
~SLList ( void ) ; // 析构函数
bool IsEmpty ( void ) const { return headnext = = NULL ; } ; // 判断链表是否为空
int length ( void ) const ; // 返回表的长度
bool Find ( int k, T & item ) const ; /*存取:将链表中第k个结点的字段值赋给item*/
int Search ( const T & item ) const ; /*查找:在链表中查找字段值为item的结点并返回其表中位置*/
void Delete ( int k, T & item ) ; /* 删除:删除链表中第k个结点并将其字段值赋给item*/
void Insert ( int k, const T & item ) ; /* 插入:在链表中第k个结点后插入字段值为item的结点*/
};
3.查找算法: 最好情况时间复杂度为O(1),最坏情况和平均情况下时间复杂度为O(n)
// 令当前指针指向链表中第k个结点,并将该结点值data返回给item
bool Find(int k, T &item)
{
if(k<1||IsEmpty())
{
cout<<"Invalid number or empty list!";
return false;
}
currptr=head;
for(int i=1; i<=k; i++)
currptr=currptr->next;
item=currptr->data;
return true;
};
4.删除算法:
// 删除当前结点的后继结点 bool Delete (T &de_item) { if(currptr==tail||IsEmpty()) { cout<<"No next node or empty list!"; return false; } SLNode<T> *temp=currptr->next; currptr->next=temp->next; size--; de_item=temp->data; // 考察被删除结点是否为原表尾 if(temp==tail) tail=currptr; delete temp; return true ; };
5.插入算法:
// 插入操作:在指定位置插入一个data域值为item的结点 // 在当前结点后插入 void Insert(const T &item) { currptr->next=new SLNode<T>(item, currptr->next); if(tail==currptr) tail=currptr->next; size++; }; // 在表尾插入结点 void InsertFromTail(const T &item) { tail->next=new SLNode<T>(item, NULL); tail=tail->next; size++; }; // 在哨位结点后插入 void InsertFromHead(const T &item) { if(IsEmpty()) { head->next=new SLNode<T>(item, head->next); tail=head->next; } else head->next=new SLNode<T>(item, head->next); size++; };(三)循环列表
1.
2. 判断空表的的条件: next(head) == head
(四)双向链表
1.定义:指链表中任一结点P都是由data域、左指针域left和右指针域right构成的,左指针域和右指针域分别存放P的左右两边相邻结点的地址信息,链表中表头结点的left指针和表尾结点的right指针均为NULL. 指针head和tail分别指向双向链表的头结点和尾结点,双向链表也被称为双重链表。
2.结构定义:双向链表结点(Double-Linked List Node)DLNode的结构定义
template < class T >
Struct DLNode{
T data;
DLNode<T> *left, *right ;
DLNode ( ) { left = right = NULL ; } ; // 构造函数
DLNode ( const T& item, SLNode * L = NULL, SLNode * R = NULL )
{ data = item ; left = L; right = R ; } // 构造函数
};
3.插入操作:
// 在当前结点后插入
void Insert(const T& item)
{
if(IsEmpty())
{
tail=head->right=new DLNode<T>(item, head, NULL);
size++;
return;
}
DLNode *p=new DLNode<T>(item, currptr, currptr->right);
currptr->right->left=p;
currptr->right=p;
size++;
// 若currptr是表尾,令表尾指针指向新插入结点
if(currptr==tail)
tail=p;
};
// 在表尾插入结点
void InsertFromTail(const T &item)
{
tail=tail->right=new DLNode<T>(item, tail, NULL);
size++;
};
// 在哨位结点后插入
void InsertFromHead(const T &item)
{
if(IsEmpty())
{
tail=head->right=new DLNode<T>(item, head, NULL);
size++;
return;
}
DLNode *p=new DLNode<T>(item, head, head->right);
head->right->left=p;
head->right=p;
size++;
};
4.删除节点: // 删除操作:删除指定结点并将其data值返回给变量de_item
// 删除哨位结点后的第一个真正表结点
bool DeleteFromHead(T &de_item)
{
if(IsEmpty())
{
cout<<"Empty list!";
return false;
}
DLNode<T> *temp=head->ri
9e9b
ght;
head->right=temp->right;
size--;
de_item=temp->data;
// 若原表中除了哨位结点外只有一个表结点
if(temp==tail)
tail=head;
delete temp;
return true;
};
// 删除表尾结点
bool DeleteFromTail(T &de_item)
{
if(IsEmpty())
{
cout<<"Empty list!";
return false;
}
SetEnd();
// 令当前指针指向表尾结点的前趋结点
Prev();
de_item=tail->data;
currptr->right=NULL;
size--;
delete tail;
tail=currptr;
return true;
};
//删除当前结点的右结点
bool Delete(T &de_item)
{
if(IsEmpty()||currptr->right==NULL)
return false;
DLNode<T>*temp=currptr->right;
de_item=temp->data;
if(temp==tail)
tail=currtpr;
else
temp->right->left=currptr;
currptr->right=temp->right;
delete temp;
size--;
return true;
};
相关文章推荐
- 数据结构(王道)【线性表】【算法1.3】
- 【算法和数据结构】线性表(四)用两个栈来实现队列(C++实现)
- 线性表链表表相关习题及详解(综合) ——数据结构
- 数据结构 线性表 建立循环链表
- 数据结构和算法——线性表
- 线性表16:双向链表 – 数据结构和算法21
- 数据结构,线性表
- 数据结构-线性表操作
- 数据结构_线性表总结_思维导图
- c语言版数据结构(奇迹冬瓜)-链表实战(2)合并两有序线性表
- 整理--数据结构--线性表
- 数据结构本质解析之----线性表与栈
- JAVA数据结构 线性表顺序是实现
- 数据结构 线性表 线性实现 c++ 源代码
- 链表练习(数据结构线性表test2)
- 数据结构 线性表算法的实现
- 数据结构:线性表删除操作的php和js实现
- 数据结构和算法学习第1天:线性表
- 数据结构---线性表---链性存
- 数据结构--1、线性表