您的位置:首页 > 理论基础 > 数据结构算法

数据结构——线性表

2016-11-24 19:45 211 查看
                                           数据结构————线性表

(一)顺序表

  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 headnext = = 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;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: