鏈表
每個數據節點除了保存數據以外,還至少有一個指針域存儲下一個節點的地址
單鏈表
每個數據節點有一個數據域一個指針域 只能從前向後檢索
- 每個元素都是一個對象,每一個對象有一個關鍵字 val 和一個指針 next(對象中還可以有其它的輔助數據 / 衛星數據);
- x 爲鏈表的一個元素,x.next 指向它的後繼元素;如果 x.next = NIL,則元素 x 沒有後繼元素,是鏈表的最後一個元素(即鏈表的尾 / tail);
- 屬性 L.head 指向鏈表的第一個元素,如果 L.head = NIL ,則鏈表爲空。
程序中的兩種逆置方法圖解:
1.頭插法逆置
// 單鏈表的逆置--頭插法逆置
void ReverseList1(LinkList list)
{
LinkList p = list->next;
LinkList q = p;//避免list->next是空鏈表
list->next = NULL;
while(p!=NULL)
{
q=p->next;
p->next = list->next;
list->next=p;
p = q;
}
}
list->next = NULL;
q=p->next;
在後面頭插入節點的時候用的是先把後面連在一起再連接前面的方法:
list->next=p;
p = q;
2.第二種倒置方法多加了一個參數k 與第一種差不多
void ReverseList2(LinkList list)
{
LinkList p = list->next;
LinkList q = NULL,k=NULL;
while(p!=NULL)
{
k=p->next;
p->next = q;
q = p;
p = k;
}
list->next=q;
}
完整程序
main.cpp
#include <stdio.h>
#include "LinkList.h"
int main()
{
LNode head;
Init_List(&head);
for (int i = 0; i < 4; ++i)
{
Insert_ListTail(&head, i + 10);
}
Show(&head);
Insert_ListHead(&head, 100);
Show(&head);
Insert_ListPos(&head, 200, 1);
Show(&head);
Insert_ListPos(&head, 300, 3);
Show(&head);
Insert_ListTail(&head, 400);
Show(&head);
Delete_ListHead(&head);
Show(&head);
Delete_ListTail(&head);
Show(&head);
Delete_ListPos(&head, 4);
Show(&head);
return 0;
}
LinkList.cpp
#include "LinkList.h"
#include <assert.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
//////////////////////////
static LinkList ApplyLNode(ElemType val, LinkList next)
{
LinkList s = (LinkList)malloc(sizeof(LNode));
assert(s != NULL);
if (s == NULL)
{
return NULL;
}
s->data = val;
s->next = next;
return s;
}
static LinkList ApplyLNode2()
{
LinkList s = (LinkList)malloc(sizeof(LNode));
assert(s != NULL);
if (s == NULL)
{
return NULL;
}
return s;
}
static int Length(LinkList list)
{
LinkList p = list->next;
int count = 0;
while (p != NULL)
{
count++;
p = p->next;
}
return count;
}
/////////////////////////
bool Init_List(LinkList list)
{
assert(list != NULL);
if (list == NULL)
{
return false;
}
list->next = NULL;
return true;
}
// 1、申請一個結點用於存儲數據
// 2、將結點插入到指定的位置:
// 1)將新結點的指針域指向原始結點的指針域
// 2)將原始結點的指針域指向新節點
bool Insert_ListHead2(LinkList list, ElemType val)
{
LinkList s = ApplyLNode2(); // 1
if (s == NULL) return false;
s->data = val;
s->next = list->next; // 2.1
list->next = s; // 2.2
return true;
}
bool Insert_ListHead(LinkList list, ElemType val)
{
LinkList s = ApplyLNode(val, list->next);
if (s == NULL) return false;
list->next = s;
return true;
}
bool Insert_ListTail(LinkList list, ElemType val)
{
LinkList p = list;
while (p->next != NULL) p = p->next;
return Insert_ListHead(p, val);
}
bool Insert_ListPos(LinkList list, ElemType val, int pos)
{
if (pos <= 0 || pos > Length(list) + 1) return false;
LinkList p = list;
for (; pos > 1; --pos) p = p->next;
return Insert_ListHead(p, val);
}
void Show(LinkList list)
{
LinkList p = list->next;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
bool Delete_ListHead(LinkList list)
{
return Delete_ListPos(list, 1);
}
bool Delete_ListTail(LinkList list)
{
return Delete_ListPos(list, Length(list));
}
bool Delete_ListPos(LinkList list, int pos)
{
if (pos <= 0 || pos > Length(list)) return false;
LinkList p = list;
for (; pos > 1; --pos) p = p->next;
LinkList q = p->next;
p->next = q->next;
free(q);
return true;
}
// 單鏈表的逆置--頭插法逆置
void ReverseList1(LinkList list)
{
LinkList p = list->next;
LinkList q = p;//避免list->next是空鏈表
list->next = NULL;
while(p!=NULL)
{
q=p->next;
p->next = list->next;
list->next=p;
p = q;
}
}
void ReverseList2(LinkList list)
{
LinkList p = list->next;
LinkList q = NULL,k=NULL;
while(p!=NULL)
{
k=p->next;
p->next = q;
q = p;
p = k;
}
list->next=q;
}
void ReverseList3(LinkList list)
{
LinkList p = list->next;
LinkList q = NULL,k=NULL;
while(p!=NULL)
{
k=p->next;
p->next = q;
q = p;
p = k;
}
}
void Clear(LinkList list)
{
while(Length(list))
{
Delete_ListHead(list);
}
}
LinkList.h
#pragma once
typedef int ElemType;
typedef struct _Node
{
ElemType data;
struct _Node *next;
}LNode, *LinkList;
bool Init_List(LinkList list);
bool Insert_ListHead(LinkList list, ElemType val);
bool Insert_ListHead2(LinkList list, ElemType val);
bool Insert_ListTail(LinkList list, ElemType val);
bool Insert_ListPos(LinkList list, ElemType val, int pos);
void Show(LinkList list);
bool Delete_ListHead(LinkList list);
bool Delete_ListTail(LinkList list);
bool Delete_ListPos(LinkList list, int pos);
// 單鏈表逆置
void ReverseList(LinkList list);