线性表,作为大家学习数据结构的第一课,也是数据结构学习过程中的第一座大山,虽然数据结构就是一山连着一山。本文中的代码内容同时给出c、c++、java的版本,对于新手来说,c语言独特的结构可以更好地理解数据结构,而c++版本则更加适合竞赛,java版本则是由学Java的同学学习。新手也可以多看看其他语言,以便后面选择语言精通。(注:数据结构不挑语言,多数后端语言都有方式实现现在及后面所学的数据结构,另,由于java不适合结构化拆分,因此只在最后给出总代码及注释)

顺序表

顺序表,用一组地址连续的存储单元来存储数据元素。最常见的顺序表是我们的老朋友——数组。鉴于常用语言都有数组,所以无论是考试还是日常使用都直接用数组即可,因此我们对顺序表的教学止步于此。

链表

链表,用一组任意的存储单元存储数据元素。(您的第一难来了)

单向链表(单链表)

单链表中分为有无头结点两种,有头结点的单链表会方便使用很多,因此我们主要教这种。(如果你想找罪受也不是不可以反正除了难用其他都差不多)

基本操作

定义结点

C
//结点定义
typedef struct LNode{
  //结点的数据域,一般结点要储存的数据都在这里定义,int可以替换成需要的数据类型,如char之类的
  int data;
  //结点的指针域,一般结点指针在这里定义。
  struct LNode* next;
}LNode,*LinkList;//LinkList为指向结构体LNode的指针类型
C++
//结点定义
typedef struct LNode{
    //结点的数据域,一般结点要储存的数据都在这里定义,int可以替换成需要的数据类型,如char之类的
	int data;
    //结点的指针域
	struct LNode* next;
    //构造函数用于创建结点(初始化)
	LNode(int x) :
        //设置结点的值为x,设置结点的下一个结点为null
		data(x), next(NULL){
	}
};

然后我们来看看链表的基本操作

初始化

C
//构造一个空的单链表(Status和OK不是c语言自带的,实际使用可以根据实际进行改变)
Status InitList(LinkList &L){
  //生成的新结点作为头结点,用头指针L指向头节点
  L = new LNode;
  //头结点的指针域置空
  L->next = NULL;
  return OK;
}

c++的初始化操作在上面的结点定义中已指出

取值

C
//在带头结点的单链表L中根据获取第i个数,用e返回该数
int* GetElem(LinkList L, int i, int &e){
  //初始化,让头结点指向p
  LNode* p = L->next;
  //计数器j初值赋为1
  int j = 1;
  //顺链查找,知道p为空或p指向第i个元素
  while(p && j < i)
  {
    //p指向下一结点
    p = p -> next;
    //计数器+1
    ++j;  
  }
  //判断i值是否合法(-1有的时候会是我们要存到链表里的数,这个要选一个与需求无关的数来定义成失败,如:我们确定要存的是正数就可以用负数或0来赋予其失败的含义)
  if(!p || j > i)
    return -1;
  //e即为第i个数
  e = p -> data;
  return e;
}
C++
//在带头结点的单链表L中根据获取第i个数,用e返回该数
int* getElement(LNode* L, int i, int &e)
{
    LNode* p = L->next;
    int j = 1;
    while (j != i && p != NULL)//当前结点不是目标结点,并且不为空时就继续搜索
    {
        j++;
        p = p->next;
    }
    e = p -> data;
    return p;//返回结果

查找

C
//查找单链表中有没有i
LNode* LocateElem(LinkList L, int i)
{
  //初始化
  LinkList p = L -> next;
  //顺链查找
  while(p && p -> data != i){
    //p指向下一结点
    p = p -> next;
  }
  //返回i所在的地址
  return p;
}
C++
LNode* listLocate(LNode* L, int x)
{
    LNode* p = L->next;//p初始指向首元素结点
    while (p != NULL && p->data != x)//p指元素结点,又不是目标节点,继续搜索下一目标
    {
        p = p->next;
    }
    return p;

插入

C
//在位置i插入e
void ListInsert(LinkList &L, int i, int e){
  LinkList p = L;
  int j = 0;
  //将p挪到位置i的前一个结点
  while(p && j < i-1){
    p = p -> next;
    ++j;
  }
  //创建要插入的结点
  LNode s;
  s -> data = e;
  //让新结点指向原来的i结点
  s -> next = p -> next;
  //让i-1结点指向新的i结点
  p -> next = s;
}
C++
bool listInsert(LNode* L, int i, int e)
{
    LNode* p = L;//p指针指向头节点
    LNode* S;
    int j = 0;
    //将p挪到位置i的前一个结点
    while (j != i - 1 && p != NULL)
    {
        p = p->next;
        j++;
    }
    if (p == NULL)
    {
        return false;//p为空指针,说明插入位置i无效,返回false
    }
    else
    {
        //此时,k=i-1,p为ei-1结点的指针
        S = new LNode;//动态申请内存,创建一个新节点,即要插入的结点
        S->data = e;
        //让新结点指向原来的i结点
        S->next = p->next;
        //让i-1结点指向新的i结点
        p->next = S;
        return true;//正确插入返回true
    }

删除

C
//删除第i个元素
void ListInsert(LinkList &L, int i){
  LinkList p = L;
  int j = 0;
  //将p挪到位置i的前一个结点
  while(p && j < i-1){
    p = p -> next;
    ++j;
  }
  //s指向要删除的元素
  LNode s = p -> next;
  //让i-1结点指向原来的i+1结点
  p -> next = s -> next;
  //删除i结点
  delete s;
}
C++
bool listInsert(LNode* L, int i, int e)
{
    LNode* p = L;//p指针指向头节点
    LNode* S;
    int j = 0;
    //将p挪到位置i的前一个结点
    while (j != i - 1 && p != NULL)
    {
        p = p->next;
        j++;
    }
    if (p == NULL)
    {
        return false;//p为空指针,说明插入位置i无效,返回false
    }
    else
    {
        //此时,p为i-1结点的指针
        S = new LNode;//动态申请内存,创建一个新节点,即要插入的结点
        S = p->next;//s指向要删除的元素
        //让i-1结点指向原来的i+1结点
        p->next = S->next;
        //删除i结点
        delete S;
        return true;//正确插入返回true
    }

前插法创建单链表

C
void CreateList_H(LinkList &L, int n){
  L = new LNode;
  L->next = NULL;
  for(i = 0; i < n; i++){
    LinkList p;
    scanf("%d", &p->data);
    p->next = L->next;
    L->next = p; 
  }
}
C++

void createListH(LNode*& L)
{
    LNode* u;
    elementType x;//存放元素数值
    L = new node;
    L->next = NULL;
    cout << "请输入元素数据(整数,9999退出):" << endl;//以9999为例
    cin >> x;
    while (x != 9999)
    {
        u = new node;//动态申请内存,产生新结点
        u->data = x;
        u->next = L->next;//新结点链接到表头,使成为首元素结点
        L->next = u;
        cin >> x;//读入下一个键盘输入数据
    }
}

后插法创建单链表

C
void CreateList_R(LinkList &L, int n){
  L = new LNode;
  L->next = NULL;
  LNode* r = L;
  for(i = 0; i < n; ++i){
    LinkList p;
    scanf("%d", &p->data);
    p->next = NULL;
    r->next = p;
    r = p; 
  }
}
C++

void createList(LNode*& L)
{
    int i, n;//n为结点个数,不含头结点
    int x;//x为数据元素值
    node* u, * R;//R为尾结点指针
    L = new node;//产生头结点
    L->next = NULL;//头结点的指针域为空
    R = L;//设置尾指针
    cout << "请输入元素结点个数(整数)" << endl;
    cin >> n;
    cout << "请输入元素数据(整数)" << endl;
    for (i = n; i > 0; i--)
    {
        u = new node;//动态申请内存,产生新结点
        cin >> x;
        u->data = x;//元素数据装入新结点
        u->next = NULL;
        R->next = u;//新结点链接到表尾
        R = u;
    }