数组
数组有上界和下界,数组的元素在上下界内是连续的。
存储10,20,30,40,50的数组的示意图如下:
数组的特点是:数据是连续的;随机访问速度快。 数组中稍微复杂一点的是多维数组和动态数组。对于C语言而言,多维数组本质上也是通过一维数组实现的。至于动态数组,是指数组的容量能动态增长的数组;对于C语言而言,若要提供动态数组,需要手动实现;而对于C++而言,STL提供了Vector;对于Java而言,Collection集合中提供了ArrayList和Vector。
单向链表
单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针。
单链表的示意图如下:
表头为空,表头的后继节点是"节点10"(数据为10的节点),"节点10"的后继节点是"节点20"(数据为10的节点),...
单链表删除节点
删除"节点30" 删除之前:"节点20" 的后继节点为"节点30",而"节点30" 的后继节点为"节点40"。 删除之后:"节点20" 的后继节点为"节点40"。
单链表添加节点
在"节点10"与"节点20"之间添加"节点15" 添加之前:"节点10" 的后继节点为"节点20"。 添加之后:"节点10" 的后继节点为"节点15",而"节点15" 的后继节点为"节点20"。
单链表的特点是:节点的链接方向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很高。
双向链表
双向链表(双链表)是链表的一种。和单链表一样,双链表也是由节点组成,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
双链表的示意图如下:
表头为空,表头的后继节点为"节点10"(数据为10的节点);"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前继节点是"节点10";"节点20"的后继节点是"节点30","节点30"的前继节点是"节点20";...;末尾节点的后继节点是表头。
双链表删除节点
删除"节点30" 删除之前:"节点20"的后继节点为"节点30","节点30" 的前继节点为"节点20"。"节点30"的后继节点为"节点40","节点40" 的前继节点为"节点30"。 删除之后:"节点20"的后继节点为"节点40","节点40" 的前继节点为"节点20"。
双链表添加节点
在"节点10"与"节点20"之间添加"节点15" 添加之前:"节点10"的后继节点为"节点20","节点20" 的前继节点为"节点10"。 添加之后:"节点10"的后继节点为"节点15","节点15" 的前继节点为"节点10"。"节点15"的后继节点为"节点20","节点20" 的前继节点为"节点15"。
下面介绍双链表的实现,分别介绍C/C++/Java三种实现。
1. C实现双链表
实现代码
#include <stdio.h>
#include "double_link.h"
void int_test()
{
int iarr[4] = {10, 20, 30, 40};
printf("\n----%s----\n", __func__);
create_dlink(); // 创建双向链表
dlink_insert(0, &iarr[0]); // 向双向链表的表头插入数据
dlink_insert(0, &iarr[1]); // 向双向链表的表头插入数据
dlink_insert(0, &iarr[2]); // 向双向链表的表头插入数据
printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 双向链表是否为空
printf("dlink_size()=%d\n", dlink_size()); // 双向链表的大小
// 打印双向链表中的全部数据
int i;
int *p;
int sz = dlink_size();
for (i=0; i<sz; i++)
{
p = (int *)dlink_get(i);
printf("dlink_get(%d)=%d\n", i, *p);
}
destroy_dlink();
}
void string_test()
{
char* sarr[4] = {"ten", "twenty", "thirty", "forty"};
printf("\n----%s----\n", __func__);
create_dlink(); // 创建双向链表
dlink_insert(0, sarr[0]); // 向双向链表的表头插入数据
dlink_insert(0, sarr[1]); // 向双向链表的表头插入数据
dlink_insert(0, sarr[2]); // 向双向链表的表头插入数据
printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 双向链表是否为空
printf("dlink_size()=%d\n", dlink_size()); // 双向链表的大小
// 打印双向链表中的全部数据
int i;
char *p;
int sz = dlink_size();
for (i=0; i<sz; i++)
{
p = (char *)dlink_get(i);
printf("dlink_get(%d)=%s\n", i, p);
}
destroy_dlink();
}
typedef struct tag_stu
{
int id;
char name[20];
}stu;
static stu arr_stu[] =
{
{10, "sky"},
{20, "jody"},
{30, "vic"},
{40, "dan"},
};
#define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) )
void object_test()
{
printf("\n----%s----\n", __func__);
create_dlink(); // 创建双向链表
dlink_insert(0, &arr_stu[0]); // 向双向链表的表头插入数据
dlink_insert(0, &arr_stu[1]); // 向双向链表的表头插入数据
dlink_insert(0, &arr_stu[2]); // 向双向链表的表头插入数据
printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 双向链表是否为空
printf("dlink_size()=%d\n", dlink_size()); // 双向链表的大小
// 打印双向链表中的全部数据
int i;
int sz = dlink_size();
stu *p;
for (i=0; i<sz; i++)
{
p = (stu *)dlink_get(i);
printf("dlink_get(%d)=[%d, %s]\n", i, p->id, p->name);
}
destroy_dlink();
}
int main()
{
int_test(); // 演示向双向链表操作“int数据”。
string_test(); // 演示向双向链表操作“字符串数据”。
object_test(); // 演示向双向链表操作“对象”。
return 0;
}
2c++实现双链表
实现代码
?
#ifndef DOUBLE_LINK_HXX
#define DOUBLE_LINK_HXX
#include <iostream>
using namespace std;
template<class T>
struct DNode
{
public:
T value;
DNode *prev;
DNode *next;
public:
DNode() { }
DNode(T t, DNode *prev, DNode *next) {
this->value = t;
this->prev = prev;
this->next = next;
}
};
template<class T>
class DoubleLink
{
public:
DoubleLink();
~DoubleLink();
int size();
int is_empty();
T get(int index);
T get_first();
T get_last();
int insert(int index, T t);
int insert_first(T t);
int append_last(T t);
int del(int index);
int delete_first();
int delete_last();
private:
int count;
DNode<T> *phead;
private:
DNode<T> *get_node(int index);
};
template<class T>
DoubleLink<T>::DoubleLink() : count(0)
{
// 创建“表头”。注意:表头没有存储数据!
phead = new DNode<T>();
phead->prev = phead->next = phead;
// 设置链表计数为0
//count = 0;
}
// 析构函数
template<class T>
DoubleLink<T>::~DoubleLink()
{
// 删除所有的节点
DNode<T>* ptmp;
DNode<T>* pnode = phead->next;
while (pnode != phead)
{
ptmp = pnode;
pnode=pnode->next;
delete ptmp;
}
// 删除"表头"
delete phead;
phead = NULL;
}
// 返回节点数目
template<class T>
int DoubleLink<T>::size()
{
return count;
}
// 返回链表是否为空
template<class T>
int DoubleLink<T>::is_empty()
{
return count==0;
}
// 获取第index位置的节点
template<class T>
DNode<T>* DoubleLink<T>::get_node(int index)
{
// 判断参数有效性
if (index<0 || index>=count)
{
cout << "get node failed! the index in out of bound!" << endl;
return NULL;
}
// 正向查找
if (index <= count/2)
{
int i=0;
DNode<T>* pindex = phead->next;
while (i++ < index) {
pindex = pindex->next;
}
return pindex;
}
// 反向查找
int j=0;
int rindex = count - index -1;
DNode<T>* prindex = phead->prev;
while (j++ < rindex) {
prindex = prindex->prev;
}
return prindex;
}
// 获取第index位置的节点的值
template<class T>
T DoubleLink<T>::get(int index)
{
return get_node(index)->value;
}
// 获取第1个节点的值
template<class T>
T DoubleLink<T>::get_first()
{
return get_node(0)->value;
}
// 获取最后一个节点的值
template<class T>
T DoubleLink<T>::get_last()
{
return get_node(count-1)->value;
}
// 将节点插入到第index位置之前
template<class T>
int DoubleLink<T>::insert(int index, T t)
{
if (index == 0)
return insert_first(t);
DNode<T>* pindex = get_node(index);
DNode<T>* pnode = new DNode<T>(t, pindex->prev, pindex);
pindex->prev->next = pnode;
pindex->prev = pnode;
count++;
return 0;
}
// 将节点插入第一个节点处。
template<class T>
int DoubleLink<T>::insert_first(T t)
{
DNode<T>* pnode = new DNode<T>(t, phead, phead->next);
phead->next->prev = pnode;
phead->next = pnode;
count++;
return 0;
}
// 将节点追加到链表的末尾
template<class T>
int DoubleLink<T>::append_last(T t)
{
DNode<T>* pnode = new DNode<T>(t, phead->prev, phead);
phead->prev->next = pnode;
phead->prev = pnode;
count++;
return 0;
}
// 删除index位置的节点
template<class T>
int DoubleLink<T>::del(int index)
{
DNode<T>* pindex = get_node(index);
pindex->next->prev = pindex->prev;
pindex->prev->next = pindex->next;
delete pindex;
count--;
return 0;
}
// 删除第一个节点
template<class T>
int DoubleLink<T>::delete_first()
{
return del(0);
}
// 删除最后一个节点
template<class T>
int DoubleLink<T>::delete_last()
{
return del(count-1);
}
#endif
|