数据结构复习(二)—链表
链表基本分类
1.单链表
2.双链表
3.循环链表
链表定义和图示化表达
简言之,就是data加next指针打包在一起的信息集;
链表的基本操作:
1.链表的定义
#define Elemtype int
typedef struct LNode
{
Elemtype data;
LNode* next;
}LinkList;
2.链表的基本操作
1.头插法建表
void CreateListHead(LinkList*&L, int a[],int n)
{
L=(LinkList*)malloc(sizeof(LinkList));
LinkList *s; //存储待插入的节点信息
L->next = NULL; //头插法得到的是逆序的原数组,尾节点最后指向NULL
for (int i=0;i<n;i++)
{
s=(LinkList*)malloc(sizeof(LinkList));
s->data = a[i];
s->next = L->next;
L->next = s;
}
}
2.尾插法建表
void CreateListTail(LinkList*&L,int a[],int n)
{
L= (LinkList*)malloc(sizeof(LinkList));
LinkList *s,*r;//s作为每次的存储节点,r作为哨兵进行记录
r=L;
for(int i = 0;i<n;i++)
{
s=(LinkList*)malloc(sizeof(Linklist));
s->data=a[i];
s->next=r->next;
r->next=s;
}
r->next = NULL;
}
3.初始化链表
void InitList(*&L)
{
L=(LinkList*)malloc(sizeof(LinkList));
L->next = NULL;
}
4.销毁链表
void DistroyList(*&L)
{
LinkList *pre = L;
LinkList *p=L->next;
while(p!=NULL)
{
free(pre);
pre=p;
p=p->next;
}
free(pre);
}
5.判断链表是否为空表
bool ListEmpty(*L)
{
return (L->next = NULL);
}
6.求链表的长度
int Listlength(*L)
{
int n=0;
while(L->next != NULL)
{
n++
L=L->next;
}
return n;
}
7.输出链表
void PrintList(LinkList *L)
{
LinkList *p = L->next;
while(p != NULL )
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
8.求线性表L中指定位置的某个数据元素
bool GetElem(LinkList* L, int pos,int &value)
{
LinkList *p= L;
for(int i=0;i<pos&&p!=NULL;i++)
{
p=p->next;
}
if(p==NULL)
return false;
else{
value = p->data;
return true;
}
}
9.查找特定元素值
bool LocateEleme(Linklist *L,int value)
{
int i =1;//位序和顺序要做一个区分
Linklist *p=L;
while(p->data!=value && p!= NULL)
{
i++;
p=p->next;
}
if(p==NULL)
return 0;
else
return i;
}
10.插入数据
bool InsertEleme(Linklist *&L, int pos,int value)//pos存储位序
{
LinkList *p = L;
LinkList *pre,*s;
int i = 0;
while(i<pos && p!=NULL)
{
i++;
p=p->next;
}
if(p==NULL)
{
return false;
}
else
{
s = (LinkList*)malloc(sizeof(LinkList));
s->data = value;
s->next = p->next;
p->next = s;
return true;
}
}
11.删除数据
bool DelElem(LinkList *&L, int i,int value)
{
LinkList *p = L;
LinkList *q;
int j = 0;
while(j < i-1 && p!= NULL)
{
if(p==NULL)
{
return false;
}
else {
s = p->next;
if(s==NULL)
return false;
else{
value = s->data;
p->next = s->next;
free(s);
}
}
}
}
3.链表基本操作合集
#include <iostream>
#include <random>
using namespace std;
#define Elemtype int
#define Maxsize 50
const int n = 10;
typedef struct LNode {
Elemtype data;
LNode* next;
}LinkList;
//头插法建表
void CreateListH(LinkList *&L, int a[],int n)
{
LinkList* s;
L = (LinkList*)malloc(sizeof(LinkList));
L->next = NULL;
for (int i = 0; i < n; i++)
{
s = (LinkList*)malloc(sizeof(LinkList));
s->data = a[i];
s->next = L->next;
L->next = s;
}
}
//尾插法建表
void CreateListT(LinkList*& L, int a[],int n)
{
LinkList* s,*r;//r作为一个哨兵
L = (LinkList*)malloc(sizeof(LinkList));
r = L;
for (int i = 0; i < n; i++)
{
s = (LinkList*)malloc(sizeof(LinkList));
s->data = a[i];
r->next = s;
r = s;
}
r->next = NULL;//使尾节点的next指向null
}
//打印表
void PrintList(LinkList*& L)
{
while (L != NULL)
{
cout << L->data << " ";
L = L->next;
}
cout << endl << endl;
}
int main()
{
LinkList *L;
int a[n];
for (int i = 0; i < n; i++)
{
a[i] = 1 + rand() % 100;
}
for (int i = 0; i < n; i++)
{
cout << a[i] << " ";
}
cout << endl << endl;
CreateListH(L, a, n);
PrintList(L);
CreateListT(L, a, n);
PrintList(L);
return 0;
}
编程过程中的一些体会
1.关于要不要用引用,就看这个函数的本身目的是不是让原阿里的链表发生改变,如果是“增删改”这些操作那自然是要的,如果只是像“改”这样的操作
链表考研层面基本题型
1.单链表逆置
方法一:
将表L的头节点与其后续部分断开,遍历后续部分,执行插到L的头节点后
方法二: