1. 引言
本文主要讲解一些常见的关于链表的算法和面试题。
2. 单链表的反序(不带头结点)
/* 不带头结点的单链表逆转 */
#include "ds.h"
using namespace std;
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
void InitList(LinkList &L);
void TailCreList(LinkList &L, int n);
void ReverseList(LinkList &L);
void TraverseList(LinkList L);
void InitList(LinkList &L)
{
L = NULL;
}
void TailCreList(LinkList &L, int n)
{
LinkList p, tail, s;
int i;
if (0 > n)
return;
tail = L;
printf("please input %d number:", n);
for (i = 1; i <= n; i++)
{
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &(s->data));
if (1 == i)
{
s->next = tail;
L = tail = s;
}
else
{
tail->next = s;
tail = tail->next;
}
}
tail->next = NULL;
}
void ReverseList(LinkList &L)
{
LinkList pre_pre, pre, cur;
// 链表为空和只有一个元素时不用逆转
if (NULL == L || NULL == L->next)
return;
cur = L;
pre = NULL;
// 从第二个元素开始逆转,
while (cur->next)
{
// pre_pre, pre, cur 向前移动
pre_pre = pre;
pre = cur;
cur = cur->next;
// 开始逆转
pre->next = pre_pre;
}
// 将最后一个结点指向其前驱
cur->next = pre;
// 头指针指向最后一个结点L
L = cur;
}
void TraverseList(LinkList L)
{
LinkList p = L;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
LinkList L;
InitList(L);
TailCreList(L, 5);
TraverseList(L);
ReverseList(L);
TraverseList(L);
}
3. 输入一个单向链表,输出该链表中倒数第 k 个结点。
// 输入一个单向链表,输出该链表中倒数第 k 个结点。
#include "ds.h"
using namespace std;
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
void InitList(LinkList &L);
void TailCreList(LinkList &L, int n);
int OutputLast_K(LinkList L, int k);
void TraverseList(LinkList L);
void InitList(LinkList &L)
{
L = NULL;
}
void TailCreList(LinkList &L, int n)
{
LinkList p, tail, s;
int i;
if (0 > n)
return;
tail = L;
printf("please input %d number:", n);
for (i = 1; i <= n; i++)
{
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &(s->data));
if (1 == i)
{
s->next = tail;
L = tail = s;
}
else
{
tail->next = s;
tail = tail->next;
}
}
tail->next = NULL;
}
/*
返回值说明:
0 -> 输出成功
-1 -> 链表为空或k<1
-2 -> 链表长度小于k
*/
int OutputLast_K(LinkList L, int k)
{
LinkList p_k = L, p_add_k = L;
int i = 0;
// 链表为空和k<1
if (NULL == L || k < 1)
{
if (k < 1)
printf("k < 1 \n");
return -1;
}
// 当p_add_k到链表尾部时,p_k到倒数第k个结点处
while (p_add_k)
{
if (i < k)
{
i++;
}
else
{
p_k = p_k->next;
}
p_add_k = p_add_k->next;
}
// 链表长度大于等于K
if (i == k)
{
while (p_k)
{
printf("%d ", p_k->data);
p_k = p_k->next;
}
printf("\n");
}
// 链表长度小于K
else
{
printf("List L less %d element.\n", k);
return -2;
}
return 0;
}
void TraverseList(LinkList L)
{
LinkList p = L;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
LinkList L;
InitList(L);
TailCreList(L, 5);
TraverseList(L);
for (int i = 0; i < 8; i++ )
OutputLast_K(L, i);
}