您的位置:首页 > 其它

链表ADT实现

2016-08-16 22:29 169 查看

链表的定义:

链表链表有一系列不必再内存中连续的结构组成,不需要使用地址连续的存储单元。它是通过“链”来建立逻辑关系的,因此在对链表进行插入,删除操作时不需要移动元素,而只需要修改指针即可。

链表分类:按是否包含指向前继的指针可分为单链表和双向链表;按是否成环状可以分为循环链表和非循环链表。

由于连表示离散的分布在存储空间的,因此链表是非随机存取的,只能从某个特定节点开始遍历一次查找。

通常为方便操作,在链表第一个节点前附加一个头节点,头节点的指针与指向链表的第一个元素节点。

链表的实现与常见算法

单链表

  每个结构含有表元素和指向包含该元素后继的结构的指针。除了头节点,每一个结点都有唯一的前继。除最后一个结点,每一个结点都有一个后继。


插入:


删除:


双向链表

双向链表与单链表的不同之处在于,双向链表的每个结点含有两个指针域,其中一个指向直接前继,一个指向直接后继。这样双向链表可以沿两个方向进行遍历;
插入:
删除:


struct LNode {
ElementType e;
PtrToLNode Next;
};
typedef struct LNode *PtrToLNode;
typedef PtrToLNode List;
List List_Init(void)
{
List L = (List)malloc(sizeof(LNode));
L->Next = NULL;
return L;
}

int List_IsEmpty(List L)
{
if (L->Next = NULL)
return 1;
else
return 0;
}

void List_Print(List L)
{
PtrToLNode p = L->Next;
while (p){
printf("%d\t", p->e);
p = p->Next;
}
printf("\n");
}

void List_Pre_Create(List L)//头插法建立单链表
{
ElementType x;
scanf("%d", &x);
while (x != 9999) {
PtrToLNode p = (PtrToLNode)malloc(sizeof(LNode));
p->e = x;
p->Next = L->Next;
L->Next = p;
scanf("%d", &x);
}
}

void List_Post_Create(List L)//尾差法建立单链表
{
ElementType x;
PtrToLNode p, r = L;
scanf("%d", &x);
while (x != 9999) {
p = (PtrToLNode)malloc(sizeof(LNode));
p->e = x;
r->Next = p;
r = p;
scanf("%d", &x);
}
r->Next = NULL;
}

PtrToLNode List_FindPre(List L, PtrToLNode r)//返回结点r的直接前继
{
PtrToLNode pre = L, p = pre->Next;
while (p != r) {
pre = p;
p = p->Next;
}
return pre;
}

int List_Length(List L)//求链表长度
{
int Length = 0;
PtrToLNode p = L->Next;
while (p) {
++Length;
p = p->Next;
}
return Length;
}

void List_Insert(List L, Position p, ElementType x)//在结点p处插入新节点
{
PtrToLNode pre = List_FindPre(L, p), s;
s = (PtrToLNode)malloc(sizeof(LNode));
s->e = x;
s->Next = p;
pre->Next = s;
}

PtrToLNode List_FindMid(List L)//返回中间元素结点
{
PtrToLNode p, r;
p = r = L->Next;
while (r->Next != NULL && r->Next->Next != NULL){
p = p->Next;
r = r->Next->Next;
}
printf("%d\n", p->e);
return p;
}

void List_Delete(List L, ElementType x)//删除节点
{
PtrToLNode pre = L, p = L->Next, temp;
while (p){
if (p->e != x) {
pre = p;
p = p->Next;
}
else{
temp = p->Next;
pre->Next = temp;
free(p);
p = temp;
}
}
}

void List_DeleteRepeat(List L)//删除有序链表中重复元素的结点
{
PtrToLNode pre = L->Next, p = pre->Next, temp;
while (p){
if (pre->e == p->e) {
temp = p->Next;
pre->Next = temp;
free(p);
p = temp;
}
else {
pre = p;
p = p->Next;
}
}
}

PtrToLNode List_Last_K(List L, int k)//返回倒数第K个结点
{
PtrToLNode p, r;
p = r = L;
if (k > List_Length(L)) {
printf("The k is Bigger Than L's Length!\n");
return NULL;
}
for (int i = 0; i < k; ++i)
r = r->Next;
while (r){
r = r->Next;
p = p->Next;
}
printf("%d\n", p->e);
return p;
}
/*若两单链表有公共结点,则从起始公共结点至尾结点两者均相同,因此将两链表尾部对齐,开始比较第一个相同结点即为起始公共结点*/
PtrToLNode List_CommonNode(List L1, List L2)//返回两单链表的公共起始节点
{
int Length1, Length2, dist;
PtrToLNode longlist, shortlist;
Length1 = List_Length(L1);
Length2 = List_Length(L2);
if (Length1 > Length2) {
longlist = L1->Next;
shortlist = L2->Next;
dist = Length1 - Length2;
}
else {
longlist = L2->Next;
shortlist = L1->Next;
dist = Length2 - Length1;
}
while (dist--)
longlist = longlist->Next;
while(longlist && longlist->e != shortlist->e){
longlist = longlist->Next;
shortlist = shortlist->Next;
}
PtrToLNode p = longlist;
while (p) {
printf("%d\n", p->e);
p = p->Next;
}
return longlist;
}

void List_Reverse(List L)//
{
PtrToLNode pre, p, r;
pre = L;
p = pre->Next;
r = p->Next;
p->Next = NULL;//将逆置后的p将成为尾结点,将其指针域置空
while (r) {
pre = p;
p = r;
r = r->Next;//遍历链表
p->Next = pre;//逆置
}
L->Next = p;//p结点将成为你逆置后的第一个节点,将头节点指向该节点
}
</pre><pre name="code" class="cpp"><pre name="code" class="cpp">void List_Reverse1(List L)//利用头插法逆置链表
{
PtrToLNode p, r;
p = L->Next;
L->Next = NULL;
while (p) {
r = p->Next;
p->Next = L->Next;
L->Next = p;
p = r;
}
}


List List_Reverse1(List L, int m, int n)//逆置第m个结点至第n个结点结点
{
List prefirst, first, p, r;
prefirst = L;
first = p = L->Next;
for (int i = 1; i != m; ++i) {
prefirst = p;
p = p->Next;
}//prefirst指向第m-1个结点
first = p;//first指向第m个结点
for (int i = m; i <= n; ++i) {
r = p->Next;
p->Next = prefirst->Next;
prefirst->Next = p;
p = r;
}//利用头插法将m至n结点逆置
first->Next = p;//将first的指针域指向第n+1个结点
return L;
}

双链表


阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: