1.线性表的链式存储
知识点 1 | 链表:任意的存储结构(连续与否均可以) |
---|---|
知识点 2 | 链表中数据元素的逻辑顺序和存储顺序可能不一致 |
知识点 3 | 结点结构定义 typedef struct node{ Datatype data; struct node *next; }Node; |
知识点 4 | 1.无头结点的单链表 (1) 无头结点的单链表非空链表 (2) first 空表 first NULL 无头结点的单链表为空的条件是first=NULL 2.有头结点的单链表 (1) 有头结点的单链表非空链表 (2) first 空表 first 有头结点的单链表为空的条件是 first->next=NULL 头结点的作用:简化运算 |
知识点5 | 取数据域的值 p->data 取指针域的值p->next 工作指针后移P=P->next |
2.有头结点的单链表的算法
2.1 初始化空表 T(n)=O(1)
Node *Init_linklist()
{
Node * first;
first=(Node *)malloc(sizeof(Node));
first->next=NULL;
return first;
}
2.2单链表的遍历算法 T(n)=O(n)
void print_linklist(Node *first)
{
Node *p;
p=first->next;
while(p)
{
printf("%d",p->data);
p=p->next;
}
}
2.3求单链表的长度的算法 T(n)=O(n)
int length_linklist(Node *first)
{
Node *p;
int j=0;
p=first;
while(p->next)
{
j++;
p=p->next;
}
}
2.4找i位置的数据元素 T(n)=O(n)
int Get(Node *first ,int i,datatype *ptr)
{
Node *p;
int j=0;
p=first;
while(p->next &&j<i)
{
p=p->next;
j++;
}
if(j==i) {
*ptr=p->data;
return 1;
}
else {
printf("位置异常");
return 0;
}
}
2.5插入 T(n)=O(n)
int insert_linklist(Node *first ,int i,datatype x)
{
Node *p,*s;
int j=0;
p=first;
while(p->next &&j<i-1)
{
p=p->next;
j++;
}
if(j==i-1)
{
s=(Node *)malloc(sizeof(Node));
s->data=x;
s->next=p->next;
p->next=s;
}
else {printf("位置异常");
return 0;}
}
2.6头插法构造单链表 T(n)=O(n)
Node * Create_linklist(datatype r[],int n)
{
Node *first,*s;
first=(Node *)malloc(sizeof(Node));
first->next=NULL;
for(i=0;i<n;i++)
{
s=(Node *)malloc(sizeof(Node));
s->data=r[i];
s->next=first->next;
first->next=s;
}
return first;
}
2.7尾插法构造单链表 T(n)=O(n)
Node * Create_linklist(datatype r[],int n)
{
Node *first,*rear,*s;
int i;
first=rear=(Node *)malloc(sizeof(Node));
for(i=0;i<n;i++)
{
s=(Node *)malloc(sizeof(Node));
s->data=r[i];
rear->next=s;
rear=s;
}
rear->next=NULL;
return first;
}
2.8删除 T(n)=O(n)
int delete_linklist(Node *first ,int i,datatype *ptr)
{
Node *p,*s;
int j=0;
p=first;
while(p->next &&j<i-1)
{
p=p->next;
j++;
}
if(j==i-1 && p->next)
{
q=p->next;
p->next=q->next;
*ptr=q->data;
free(q);
return 1;
}
else {printf("位置异常"); return 0;}
}
2.9按值查找算法 T(n)=O(n)
int Locate_linklist(Node *first,datatype x)
{
Node *p;
int j;
p=first->next;
j=1;
while(p)
{
if(p->data==x)
{
return j;
}
p=p->next;
j++;
}
return 0;
}
2.10已知两个单链表head1和head2,把head2连接在head1后面。Head1长度为m,head2长度为n,时间复杂度为O(m)
Node *connect(Node *head1,Node *head2)
{
Node *p;
p=head1;
while(p->next)
p=p->next;
p->next=head2->next;
free(head2);
return head1;
}
2.11将两个非递减有序的单链表,合并为一个非递减有序的单链表 O(m+n)
Node *connect1(Node head1,Node head2)
{
p=head1->next;
q=head2->next;
head1->next=NULL;
rear=head1;
while(p&&q)
{
if(p->data<=q->data)
{ t=p;p=p->next;
rear->next=t;
rear=t;
}
else
{
t=q;q=q->next;
rear->next=t;
rear=t;
}
}
if(p) rear->next=p;
if(q) rear->next=q;
free(head2);
return head1;
}
2.12、将两个非递减有序的单链表,合并为一个非递增有序的单链表 O(m+n)
Node *connect1(Node head1,Node head2)
{
p=head1->next;
q=head2->next;
head1->next=NULL;
while(p&&q)
{
if(p->data<=q->data)
{ t=p;p=p->next;
t->next=first->next;
first->next=t;
}
else
{
t=q;q=q->next;
t->next=first->next;
first->next=t;
}
}
while(p)
{
t=p;p=p->next;
t->next=first->next;
first->next=t;
}
while(q)
{
t=q;q=q->next;
t->next=first->next;
first->next=t;
}
free(head2);
return head1;
}
2.13、 单链表的逆置算法 T(n)=O(n)
void reverse(Node *first)
{
Node *p,*q;
p=first->next;
first->next=NULL;
while(p)
{
q=p->next;
p->next=first->next;
first-next=p;
p=q;
}
}
2.14、判断单链表是否非递减有序 O(n)
int increase(Node *first)
{
Node *p,*t;
t=first->next;
p=t->next;
while(p && t)
{
if(t->data>p->data) return 0;
t=p;
p=p->next;
}
return 1;
}
2.15、删除单链表中所有值为x的数据元素。 O(n)
void delete_x(Node *first ,datatype x)
{
Node *p,*t;
p=first->next;
t=first;
while(p)
{
if(p->data==x)
{
t->next=p->next;
free(p);
p=t->next;
}
else{
t=p;
p=p->next;
}
}
}
2.16、单链表排序(头插法)
void sort_linklist(Node *first)
{
Node *p,*t,*q;
p=first->next->next;
first->next->next=NULL;
while(p)
{ t=p;
p=p->next;
q=first;
while(q->next&&q->next->data<t->data)
{
q=q->next;
}
t->next=q->next;
q->next=t;
}
}
3.顺序表和单链表的比较
顺序表 | 单链表 | |
---|---|---|
按位置查找 | O(1)随机存取 | O(n)顺序存取 |
按值查找 | O(n)平均比较(n+1)/2 | O(n)平均比较(n+1)/2 |
插入 | O(n)平均移动n/2 效率低 | O(n)不移动元素修改指针,效率高 |
删除 | O(n)平均移动(n-1)/2 效率低 | O(n)不移动元素修改指针,效率高 |
4.线性表的存储结构
知识点1: | 循环单链表 first 循环单链表从任意一个结点出发都能遍历整个单链表。 |
---|---|
知识点2 | 循环单链表first 单链表p指向尾结点的条件 p->next=NULL 循环单链表p指向尾结点的条件 p->next=first |
知识点3 | 循环单链表 first 头指针指示的单循环链表: 表头位置 插入O(1) 删除O(1) 表尾位置 插入O(n) 删除O(n) |
知识点4 | 存储密度:(数据本身占得存储量)/(结点所占的存储量) 顺序表:存储密度=1; 链表:存储密度<1 |
知识点5 | 静态链表工作指针j后移的语句 j=r[j].next ; |