1. 链表介绍:
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素ai与直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需要存储一个指示其直接后继的信息,这个点成为结点。
链表与顺序表不同的地方在于,它所保存的元素的地址可能是连续的,也可能是不连续的。这导致了顺序表在访问元素(尾部插入元素,指定位置修改元素等)的时间上快过链表,而链表在删除或者插入元素的时间上快过顺序表。
2.链表的功能介绍:
链表的主要功能:添加,删除,修改,倒置,排序(冒泡排序,快速排序)
(1)添加:链表的添加比较简单,分为两种,一种有位置的添加,一种尾部添加。(其实这两种都一样。)
第一种指定位置添加{add(int index,Type data)}:指定第index(从1开始)位置插入元素。先判断index是否合法,然后再找到index个位置,保留第index前一个位置的指针,以及第index个位置的指针。前继指针指向新结点,新指针指向指向后继指针。
代码如下:
template<class Type>
bool List<Type>::add(int index,Type data)
{
if(index <= 0) return false;
if(index > this->size()+1) return false;
List *p = this,*q = new List();
q->next = NULL;
q->data = data;
while(index > 1)
{
p = p->next;
index = index-1;
}
List *k = p->next;
p->next = q;
q->next = k;
return true;
}
第二种,在尾部添加元素{add(Type data)}:尾部添加比较简单,直接从头指针开始一路扫到最后一个指针,然后将最后一个指针指向新结点即可:
template<class Type>
void List<Type>::add(Type data)
{
List *p = new List(),*q = this;
p->next = NULL;
p->data = data;
while(q->next != NULL) q = q->next;
q->next = p;
}
(2)删除:链表的删除为指定位置删除。
函数原型:{remove(int index)}
介绍:链表删除前,先判断index 是否合法。合法则继续。找到index个位置的元素,保存其前继结点和后继结点的指针,将前继结点和后继结点相连,当前结点指向的下一个结点设置为NULL,删除当前结点,删除完毕。
template<class Type>
bool List<Type>::remove(int index)
{
if(index <= 0) return false;
if(index > this->size()) return false;
List *p = this,*q = p;
while(index > 0)
{
q = p;
p = p->next;
index--;
}
q->next = p->next;
p->next = NULL;
delete p;
return true;
}
(3)修改
函数原型:{set(int index,Type data)}
介绍:首先,依然是判断index是否合法,合法则继续,找到第index个位置,将其值置为data。
template<class Type>
bool List<Type>::set(int index,Type data)
{
if(index <= 0) return true;
if(index > this->size()) return false;
List *p = this;
while(index > 0)
{
index--;
p = p->next;
}
p->data = data;
return true;
}
(4)倒置
函数原型:{reverse()}
介绍:链表的倒置有很多种,有遍历一遍取出值到数组然后倒置一遍再放回去的,有从创建一条新链表,然后将原来链表逆置插入的,也有我下面这种,以当前结点为后继结点,L始终指向前面结点的前继结点。可能比较抽象,举个例子,原来链表H为12345N(N表示NULL),有一条新的链表L指向NULL,然后让H的最前面的结点指向L,然后另一个指针q指向L,L在等于q,只是为了防止L直接指向他自己。那么第一次之后就H变成了2345N,L就变成1N,第二次呢,依旧这样重复下去,直到H为空,那么链表的逆置也就完毕。
template<class Type>
void List<Type>::reverse()
{
List *head = this;
List *p = this->next->next,*q = this->next,*L = this->next;
L->next = NULL;
head->next = NULL;
while(p != NULL)
{
q = p;
p = p->next;
q->next = L;
L = q;
}
head->next = L;
}
(5)排序:
函数原型:{sort()}
介绍:我这里就只将冒泡排序,有机会我再来讲一下快速排序。冒泡排序呢,很简单,一种是让当前元素往后冒泡,一种是让后面的指针往前面冒泡,当然,这两种并没有区别,就是循环开始结束不一样而已,我也不多说。(代码可能有点乱,因为我是以它的下一个结点为NULL时结束,这个当前节点为空还是有本质上的不同。所以需要再进一步比较最后两个元素。)
template<class Type>
void List<Type>::sort()
{
List *p = this->next;
while(p->next != NULL)
{
List *q = p->next;
while(q->next != NULL)
{
if(q->data < p->data)
{
Type temp = q->data;
q->data = p->data;
p->data = temp;
}
q = q->next;
}
if(q->data < p->data)
{
Type temp = q->data;
q->data = p->data;
p->data = temp;
}
p = p->next;
}
}
3.链表的定义代码:
其中还有一些没有实现的,你们可以自己去实现以下,我也就是对自己写过的代码做个总结,希望对有需要的人有所帮助。
template<class Type>
class List
{
private:
Type data;
List *next;
void QuickSort(Type *a,int l,int r);
public:
List();
explicit List(Type data);
void add(Type data);
bool add(int index,Type data);
bool remove(int index);
bool set(int index,Type data);
void reverse();
Type get(int index);
virtual void sort();
void Qsort();
int size();
void print();
void getArray(int *a);
};