## 链表的实现与常见算法

### 单链表

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

## 双向链表

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;
}

10-30

10-29 1218
03-11 547
08-07 200
12-29 4341
03-24 484
12-03 68
09-23 374
11-04 96
01-25 2287
09-10 4862
03-18 506
10-05 110
06-18 5413
04-05 1万+
12-31