笔记
作业
1. 上课代码。循环单链表。
Loop_List.h文件。
#ifndef __LOOP_LIST_H__
#define __LOOP_LIST_H__
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
//创建单向循环链表
LinkList create_loop_list();
//创建结点
LNode* create_lnode(ElemType data);
//判空
int isEmpty(LinkList L);
//头插
void insert_head(LinkList L,ElemType data);
//打印循环单链表
void print_loop_list(LinkList L);
//尾插
void insert_tail(LinkList L,ElemType data);
//头删
void delete_head(LinkList L);
//按位置插入
void insert_pos(LinkList L,int pos,ElemType data);
//删除头结点
LinkList delete_node_head(LinkList L);
//输出删除头结点后的单向循环链表
void print_no_head(LinkList L);
#endif
Loop_List.c文件。
#include "Loop_List.h"
//创建单向循环链表
LinkList create_loop_list()
{
LinkList L=(LinkList)malloc(sizeof(LNode));
if(NULL==L)
{
printf("空间申请失败:\n");
return NULL;
}
L->data=0;
L->next=L;
return L;
}
//创建结点
LNode* create_lnode(ElemType data)
{
LNode *p=(LNode*)malloc(sizeof(LNode));
if(NULL==p)
{
printf("空间申请失败\n");
return NULL;
}
p->data=data;
return p;
}
//判空
int isEmpty(LinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return -1;
}
return L->next==L?1:0;
}
//头插
void insert_head(LinkList L,ElemType data)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
LNode *new=create_lnode(data);
new->next=L->next;
L->next=new;
L->data++;
return;
}
//打印循环单链表
void print_loop_list(LinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
if(isEmpty(L))
{
printf("链表为空\n");
return;
}
LinkList p=L->next;
while(p!=L)
{
printf("%3d",p->data);
p=p->next;
}
putchar(10);
return;
}
//尾插
void insert_tail(LinkList L,ElemType data)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
LinkList p=L;
while(p->next!=L)
{
p=p->next;
}
LNode *new=create_lnode(data);
new->next=p->next;
p->next=new;
L->data++;
return;
}
//头删
void delete_head(LinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
if(isEmpty(L))
{
printf("链表为空\n");
return;
}
LinkList p=L->next;
L->next=p->next;
free(p);
L->data--;
return;
}
//按位置插入
void insert_pos(LinkList L,int pos,ElemType data)
{
if(NULL==L)
{
printf("链表不存在\n");
}
if(pos < 1 || pos > L->data+1)
{
printf("插入位置不合理\n");
return;
}
LinkList p=L;
int count=0;
while(count!=pos-1)
{
p=p->next;
count++;
}
LNode *new=create_lnode(data);
new->next=p->next;
p->next=new;
L->data++;
return;
}
//删除头结点
LinkList delete_node_head(LinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return NULL;
}
if(isEmpty(L))
{
printf("链表为空\n");
free(L);
L=NULL;
return L;
}
LinkList p=L;
while(p->next!=L)
{
p=p->next;
}
p->next=L->next;
LinkList q=L->next;
free(L);
return q;
}
//输出删除头结点后的单向循环链表
void print_no_head(LinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
LinkList p=L;
/*
//法1
while(p->next!=L)
{
printf("%3d",p->data);
p=p->next;
}
printf("%3d",p->data);
*/
//法2
do{
printf("%3d",p->data);
p=p->next;
}while(p!=L);
putchar(10);
return;
}
main.c文件。
#include "Loop_List.h"
int main()
{
LinkList L=create_loop_list();//新建循环单链表
printf("头插法插入5个元素\n");
insert_head(L,1);
insert_head(L,2);
insert_head(L,3);
insert_head(L,4);
insert_head(L,5);
print_loop_list(L);
printf("尾插法插入1个元素\n");
insert_tail(L,6);
print_loop_list(L);
printf("头删,删除1个元素\n");
delete_head(L);
print_loop_list(L);
printf("按位插入,在第二个位置插入元素\n");
insert_pos(L,2,9);
print_loop_list(L);
printf("删除头结点,并打印删除头结点后的元素\n");
LinkList T=delete_node_head(L);//删除头结点,然后新建结点去接新的表头
L=NULL;//删除头结点后,原先的头结点要置为NULL
print_no_head(T);//删除头结点后打印
return 0;
}
2. 实现双向链表的头插、头删、尾插、尾删、按位置插入、按位置删除。
double_list.h文件。
#ifndef __DOUBLE_LIST_H__
#define __DOUBLE_LIST_H__
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct DNode {
ElemType data;
struct DNode *prior,*next;
}DNode,*DLinkList;
//创建双向链表
DLinkList create_DLinkList();
//创建新结点
DNode* create_DNode(ElemType data);
//判空
int isEmpty_DLinkList(DLinkList L);
//头插
void insert_head(DLinkList L,ElemType data);
//双链表打印
void print_DLinkList(DLinkList L);
//头删
void delete_head(DLinkList L);
//尾插
void insert_tail(DLinkList L,ElemType data);
//尾删
void delete_tail(DLinkList L);
//按位置插入
void insert_locate(DLinkList L,int pos,ElemType data);
//按位置删除
void delete_locate(DLinkList L,int pos);
#endif
double_list.c文件。
#include "double_list.h"
//创建双向链表
DLinkList create_DLinkList()
{
DLinkList L=(DLinkList)malloc(sizeof(DNode));
if(NULL==L)
{
printf("空间申请失败\n");
return NULL;
}
L->data=0;
L->prior=NULL;//头结点的prior永远指向NULL
L->next=NULL;
return L;
}
//创建新结点
DNode* create_DNode(ElemType data)
{
DNode *p=(DNode*)malloc(sizeof(DNode));
if(NULL==p)
{
printf("空间申请失败\n");
return NULL;
}
p->data=data;
p->prior=NULL;
p->next=NULL;
return p;
}
//判空
int isEmpty_DLinkList(DLinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return -1;
}
return L->next==NULL?1:0;
}
//头插
void insert_head(DLinkList L,ElemType data)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
DNode *s=create_DNode(data);
s->next=L->next;
if(L->next!=NULL)//为了防止一个结点都没有时,发生段错误
{
L->next->prior=s;
}
L->next=s;
s->prior=L;
L->data++;
return;
}
//双链表打印
void print_DLinkList(DLinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
if(isEmpty_DLinkList(L))
{
printf("链表为空\n");
return;
}
DLinkList p=L->next;
while(p!=NULL)
{
printf("%3d",p->data);
p=p->next;
}
putchar(10);
}
//头删
void delete_head(DLinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
if(isEmpty_DLinkList(L))
{
printf("链表为空\n");
return;
}
DLinkList p=L->next,q=L->next;
L->next=p->next;
if(p->next!=NULL)
{
p->next->prior=L;
}
free(q);
L->data--;
return;
}
//尾插
void insert_tail(DLinkList L,ElemType data)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
DLinkList p=L;
while(p->next!=NULL)//循环找到尾结点
{
p=p->next;
}
DNode *s=create_DNode(data);
s->next=p->next;
s->prior=p;
p->next=s;
L->data++;
return;
}
//尾删
void delete_tail(DLinkList L)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
if(isEmpty_DLinkList(L))
{
printf("链表为空\n");
return;
}
DLinkList p=L,q;
while(p->next->next!=NULL)//循环找到尾结点的前驱
{
p=p->next;
}
q=p->next;
p->next=NULL;
free(q);
L->data--;
return;
}
//按位置插入
void insert_locate(DLinkList L,int pos,ElemType data)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
if(pos<1 || pos>L->data+1)
{
printf("插入位置不合理\n");
return;
}
//方法1
DLinkList p=L;
int count=0;
while(count!=pos-1)
{
p=p->next;
count++;
}
DNode *s=create_DNode(data);
s->next=p->next;
if(p->next!=NULL)//为了防止再长度加1的位置插入时发生段错误
{
p->next->prior=s;
}
p->next=s;
s->prior=p;
L->data++;
/*
//方法2,太麻烦
DLinkList p=L->next;
int count=1;
while(count!=pos)
{
p=p->next;
count++;
}
DNode *s=create_DNode(data);
if(p!=NULL)
{
p->prior->next=s;
s->prior=p->prior;
s->next=p;
p->prior=s;
}else if(NULL==p)
{
p=L;
while(p->next!=NULL)
{
p=p->next;
}
s->next=p->next;
s->prior=p;
p->next=s;
}
*/
L->data++;
return;
}
//按位置删除
void delete_locate(DLinkList L,int pos)
{
if(NULL==L)
{
printf("链表不存在\n");
return;
}
if(isEmpty_DLinkList(L))
{
printf("链表为空\n");
return;
}
if(pos<1 || pos>L->data)
{
printf("删除位置不合理\n");
return;
}
DLinkList p=L,q;
int count=0;
while(count!=pos-1)
{
p=p->next;
count++;
}
q=p->next;
p->next=q->next;
if(q->next!=NULL)
{
q->next->prior=p;
}
free(q);
L->data--;
return;
}
main.c文件。
#include "double_list.h"
int main()
{
printf("双链表头插建立链表:\n");
DLinkList L=create_DLinkList();//创建双链表
insert_head(L,1);//头插
insert_head(L,2);
insert_head(L,3);
insert_head(L,4);
insert_head(L,5);
print_DLinkList(L);
printf("头删一个元素后的结果:\n");
delete_head(L);//头删
print_DLinkList(L);
printf("尾插两个元素后的结果:\n");
insert_tail(L,6);//尾插
insert_tail(L,7);
print_DLinkList(L);
//printf("%d\n",L->data);
printf("尾删一个元素后的结果:\n");
delete_tail(L);//尾删
print_DLinkList(L);
//printf("%d\n",L->data);
printf("在第2个位置插入9:\n");
insert_locate(L,2,9);
print_DLinkList(L);
printf("删除第6个位置上的值:\n");
delete_locate(L,6);
print_DLinkList(L);
return 0;
}
3. 总结链表和顺序表的区别。
顺序表可以随机访问;且存储密度高;在除表尾之外,靠前面的位置插入和删除元素需要移动大量元素。链表不能随机访问;存储密度低;插入和删除元素的平均时间复杂度为O(n),但时间主要浪费在查找上,单纯插入和删除操作时间复杂度为O(1)。
4. 链表逆置。
方法1:
void reverse_link01(LinkList SL)
{
if(NULL==SL)
{
printf("链表不存在\n");
return;
}
if(isEmpty_link(SL))
{
printf("链表为空\n");
return;
}
if(NULL==SL->next->next)//只有一个结点时,不用逆置
{
return;
}
//p为先保留的第二个结点,q暂时为野指针
LinkList p=SL->next->next,q;
SL->next->next=NULL;//让第一个结点指向NULL
while(p!=NULL)
{
q=p->next;//在头插之前保留下一个要头插的结点的首地址
p->next=SL->next;//头插
SL->next=p;
p=q;//让p指向下一个要头插的结点
}
}
方法2:
void reverse_link02(LinkList SL)
{
if(NULL==SL)
{
printf("链表不存在\n");
return;
}
if(isEmpty_link(SL))
{
printf("链表为空\n");
return;
}
if(NULL==SL->next->next)//链表只有一个元素时,不需要逆置
{
return;
}
LinkList p=SL->next,q=p->next,t=q->next;
while(t!=NULL)
{
q->next=p;
p=q;
q=t;
t=t->next;
}
q->next=p;
SL->next->next=NULL;
SL->next=q;
}