链接方式存储的线性表简称为链表(Linked List)。
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
注意:
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
2、链表的结点结构
┌──┬──┐
│data│next│
└──┴──┘
data域--存放结点值的数据域
测试输入数据文件 list.txt
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
注意:
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
2、链表的结点结构
┌──┬──┐
│data│next│
└──┴──┘
data域--存放结点值的数据域
next域--存放结点的直接后继的地址(位置)的指针域(链域)
3、头指针head和终端结点指针域的表示
单链表中每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始结点,头指针head是个特殊的指针,他就是链表的带头大哥,找到他就可以访问链表中的数据。
终端结点无后继,故终端结点的指针域为空,即NULL。
4、好了,废话少说,上代码
关于链表定义的代码,LinkedList.h
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
#include <cstdlib>
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::cerr;
template <class T>
struct LinkNode
{
T data;//值域
LinkNode<T> *link;//指针域
LinkNode(LinkNode<T> *ptr = nullptr)
{
link = ptr;
}
LinkNode(const T& item,LinkNode<T> *ptr = nullptr)
{
data = item;
link = ptr;
}
};
template <class T>
class List
{
public:
List()//构造函数
{
first = new LinkNode<T>;
length = 0;
}
~List()//析构函数
{
clear();
delete first;
}
int Length()const;//返回链表长度
LinkNode<T> *getHead()const{
return first;
}
LinkNode<T> *Search(const T &x);//查找x是否存在链表中
void clear();//清空链表,仅余头结点
LinkNode<T> *locate(int i) const;//返回第i个元素,元素下标从1开始
bool insert(int i,T& t);//在第i个位置插入元素
bool remove(int i);//移除第i个位置插入元素
void inverse();//链表翻转
bool isEmpty()const{
return (first->link == nullptr)?true:false;
}
friend istream& operator >> (istream &in,List<T> &list)
{
list.clear();//首先list清空
LinkNode<T> *first,*last;
first = list.first;
last = first;
while(!in.eof())
{
T val;
in >> val;
LinkNode<T> *node = new LinkNode<T>(val);
last->link = node;
list.length++;
last = node;
}
last->link = nullptr;//尾结点指向空
return in;
}
friend ostream& operator << (ostream& out,const List<T> &list)
{
LinkNode<T> *p = list.first->link;
int i = 1;
while(p != nullptr)
{
cout <<"#" << i <<":" << p->data << endl;
p = p->link;
++i;
}
return out;
}
protected:
LinkNode<T> *first;//记录链表头指针
int length;//记录链表长度
};
template <class T>
void List<T>::clear()
{
LinkNode<T> *p = first->link;
LinkNode<T> *q;
while(p != nullptr)
{
q = p;
p = p->link;//p向后移
first->link = p;//重新与头结点建立联系
delete q;//删除结点
length--;
}
}
template <class T>
LinkNode<T> * List<T>::Search(const T &x)
{
LinkNode<T> *p = this->first->link;
while(p != nullptr)
{
if(p->data == x)
{
return p;
}
p = p->link;
}
return p;
}
template <class T>
LinkNode<T> * List<T>::locate(int i) const
{
if(i == 0)
{
return first;
}
if(i < 0 || i > length)
{
return nullptr;
}
LinkNode<T> *p = first->link;
for(int j = 1; j < i; j++)
{
p = p->link;
}
return p;
}
template <class T>
bool List<T>::insert(int i,T& t)
{
LinkNode<T> *current = locate(i-1);
if(current == nullptr)
{
return false;
}
LinkNode<T> *node = new LinkNode<T>(t);
if(node == nullptr)
{
cerr << "memory malloc failed!" << endl;
exit(1);
}
node->link = current->link;
current->link = node;
++length;
return true;
}
template <class T>
bool List<T>::remove(int i)
{
LinkNode<T> *current = locate(i-1);
if(current == nullptr)
{
return false;
}
LinkNode<T> *p = current->link;
current->link = p->link;
delete p;
length--;
return true;
}
template <class T>
void List<T>::inverse()
{
LinkNode<T> *p, *pr,*temp;
temp = NULL;
p = first->link;
while (p != nullptr){
pr = p;
first->link = pr;
p = p->link;
pr->link = temp;//pr为当前节点,pr的link指向上次记住的节点
temp = pr;//记住节点,下次循环要用
}
}
#endif
测试代码,main.cpp
#include "LinkedList.h"
#include <fstream>
using std::ifstream;
using std::ios;
int main()
{
List<int> list;
//list.init();
ifstream in = ifstream("list.txt",ios::in);
in >> list;
cout << "The initial list in the file is:\n" << list << endl;
list.inverse();
cout << "The inverse list in the file is:\n" << list << endl;
/*
cout << "input the number you want search:";
int number;
cin >> number;
LinkNode<int> *p = list.Search(number);
if(p == nullptr)
{
cout << number << " not exsited" << endl;
}
else
{
cout << number << " exsited" << endl;
}
list.clear();
cout << "The cleaded list in the file is:\n" << list << endl;*/
/*cout << "input the index you want locate:";
int index;
cin >> index;
LinkNode<int> *p = list.locate(index);
if(p == nullptr)
{
cout << "element at " << index << " not exsited" << endl;
}
else
{
cout << "element at " << index << " is " << p->data <<endl;
}*/
/*cout << "input the index、value you want insert ,split by space ";
int index;
int value;
cin >> index >> value;
if(list.insert(index,value))
{
cout << list << endl;
}*/
/*cout << "input the index you want delete ";
int index;
cin >> index ;
if(list.remove(index))
{
cout << list << endl;
}*/
in.close();
system("pause");
return 0;
}
/*
int main()
{
ifstream in = ifstream("list.txt",ios::in);
int num;
if(!in)
{
cout << "文件打不开" << endl;
}
else
{
while(in >> num)
{
cout << num;
}
}
in.close();
system("pause");
return 0;
}*/
测试输入数据文件 list.txt
1 2 3 4 5 6 7 8