单链表
单链表
线性表的链式存储结构。
优点是链式存储的空间分配灵活、高效。
链表只能从表头顺序存取元素,能够较为快速的插入删除元素,并且不需要移动元素。
另外,链式存储结构可以更方便的表示各种逻辑结构。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef struct LNode{
int data;
struct LNode *next;
}LNode, *LinkList;
/*
上述代码等价
先定义结点
struct LNode{
int data;
struct LNode *next;
}
后重命名
typedef struct LNode LNode;//结点
typedef struct LNode *LinkList;//链表
*/
//初始化带头结点的单链表
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));//分配一个头结点
if (L == NULL)
return false;
L->next = NULL;
return true;
}
/*
//初始化无头结点的单链表
bool InitList(LinkList &L){
L = NULL;
return true;
}
*/
//头插法(链表的逆置)
LinkList List_HeadInsert(LinkList &L){
LNode *s; int x;
L = (LinkList)malloc(sizeof(LNode));//创建头结点
L->next = NULL;
scanf("%d", &x);
while(x != 9999){
s = (LNode*)malloc(sizeof(LNode));//创建新结点
s->data = x;
s->next = L->next;
L->next = s;//将新结点插入链表中,L为头指针
scanf("%d", &x);
}
return L;
}
//尾插法
LinkList List_TailInsert(LinkList &L){
int x;
L = (LinkList)malloc(sizeof(LNode));
LNode *s,*r = L;//r为尾指针
scanf("%d", &x);
while (x != 9999){
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;//永远保持r指向最后一个结点
scanf("%d", &x);
}
r->next = NULL;
return L;
}
//求表的长度
int Length(LinkList L){
int len = 0;
LNode *p;
p = L;
//不带头结点p!=NULL
while (p->next != NULL){
p = p->next;
len ++;
}
return len;
}
//按序查找
LNode *GetElem(LinkList L, int i){
if (i < 0)
return NULL;
LNode *p;
int j = 0;
p = L;
while (p != NULL && j < i){
p = p->next;
j ++;
}
return p;
}
//按值查找
LNode *LocateElem(LinkList L, int e){
LNode *p = L->next;
while (p != NULL && p->data != e){
p = p->next;
}
return p;
}
//后插操作
bool InsertNextNode(LNode *p, int e){
if (p == NULL)
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
//前插操作
bool InsertPriorNode(LNode *p, int e){
if (p == NULL)
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->next = p->next;
p->next = s;
s->data = p->data;
p->data = e;
return true;
}
//按位序插入(带头结点)
bool ListInsert(LinkList &L, int i, int e){
if (i < 1)
return false;
LNode *p = GetElem(L,i - 1);
return InsertNextNode(p,e);
}
/*
//按位序插入(不带头结点)
bool ListInsert(LinkList &L, int i, int e){
if (i < 1)
return false;
if (i == 1){
LNode *s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = L;//此时L=NULL
L = s;//头指针指向新结点
return true;
}
LNode *p;
int j = 1;//当前p指向第几个结点
p = L;//p指向第一个结点(注意:非头结点)
while (p != NULL && j < i - 1){
p = p->next;
j ++;
}
//LNode *p = GetElem(L,i - 1);
return InsertNextNode(p,e);
}
*/
//按位序删除(带头结点)
bool ListDelete(LinkList &L, int i, int &e){
if (i < 1)
return false;
LNode *p = GetElem(L,i - 1);
if (p == NULL)
return false;
LNode *q = p->next;
e = q->data;
p->next = q->next;
free(q);
return true;
}
//删除指定结点
bool DeleteNode(LNode *p){
if (p == NULL)
return false;
LNode *q = p->next;//令q指向p的后继结点
p->data = p->next->data;//和后继结点交换数据域
p->next = q->next;//将q结点从链中断开
free(q);//释放后继节点
return true;
}
//打印链表
void PrintList(LinkList L){
LNode *p = L->next;
while (p != NULL){
cout << p->data <<' ';
p = p->next;
}
cout << endl;
}
int main()
{
cout << "-------TestTailInsert-------" << endl;
LinkList L;
InitList(L);
List_TailInsert(L);
PrintList(L);
cout << Length(L) << endl;
cout << "-------TestInsert-------" << endl;
ListInsert(L,1,2);
PrintList(L);
cout << Length(L) << endl;
ListInsert(L,2,16);
PrintList(L);
cout << Length(L) << endl;
cout << "-------TestSerch-------" << endl;
cout << GetElem(L,2)->data << endl;
cout << LocateElem(L,16)->data << endl;
cout << "-------TestDelete-------" << endl;
int e = 0;//暂时保存被删除数值
ListDelete(L,1,e);
ListDelete(L,1,e);
PrintList(L);
cout << Length(L) << endl;
cout << "-------TestPriorInsert-------" << endl;
LinkList K;
InitList(K);
List_HeadInsert(K);
PrintList(K);
return 0;
}
/*
6 5 5 3 6 9999
6 5 5 3 6 9999
*/