目录
链式存储:
线性结构中每个结点只有一个前驱和一个后继,设定更关心它的后继,这样在存储时除了存放结点的信息外,只要附设一个指针指向它的后继结点的存放位置。
每个结点的储存位置是:
单链表:
定义:
单链表中的结点一般含有两个域,一个是存放信息的 info域 ,另一个是指向下一个结点的存放地址的指针域next
单链表的C语言描述:
typedef int datatype;
typedef struct link_node{
datatype info;
struct link_node *next;
}node;
建立一个空的单链表
node *init_link_list()
{
return NULL;
}
输出单链表中各个结点的值
void print_link_list(node *head)
{
node *p;
p = head;
if(!p) printf("\n单链表是空的!");
else
{
printf("\n各个结点的值为:\n");
while(p)
{
printf("%5d",p->info);
p = p->next;
}
}
}
在电链表中查找一个值为x的结点:
node *find_num_link_list(node *head,datatype x)
{
node *p;
p = head;
while(p && p -> info != x) p = p -> next;
return p;
}
在单链表中查找第i个结点
node *find_pos_link_list(node *head,int i)
{
int j = 1;
node *p = head;
if(i < 1)
{
printf("\nerror\n");
exit(1);
}
while(p &&i != j)
{
p = p->next;
j ++;
}
return p;
}
插入一个值为x的结点作为单链表的第一个节点
node *insert_in_front_link_list(node *head,datatype x)
{
node *p;
p =(node*)malloc(sizeof(node)); //使用stdlib头文件
p->info=x;
p->next=head;
head=p;
return head;
}
在单链表中第i个结点后插入一个值为x的新结点
node *insert_x_after_i(node *head,datatype x,int i)
{
node *p , *q;
q = find_pos_link_(head,i);
if(!q)
{
printf("\n找不到第%d个结点%d,不能进行插入!",i,x);
exit(0);
p=(node*)malloc(sizeof(node));
p->info=x;
p->next=q->next;
q->next=p;
return head;
}
}
在单链表中删除一个值为x的结点
node *delete_num_link_list(node *head,datatype x)
{
node *pre=NULL,*p;
if(!head)
{
printf("单链表是空的!");
return head;
}
p=head;
while(p&&p->info=x) //删除除第一个结点的情况
{
pre=p;
p=p->next;
}
if(!pre&&p->info==x) head=head->next;//删除第一个节点的情况
else pre->next=p->next;
free(p);
return head;
}
带头结点的单链表
建立一个带头结点的单链表:
node *init_hlink_link_list()
{
node *head;
head=(node*)malloc(sizeof(node));
head->next=NULL;
return head;
}
建立一个空的单链表:(插曲)
node *init_link_link()
{
return NULL;
}
输出带头结点单链表中各个结点的值:
void print_hlink_list(node *head)
{
node *p;
p=head->next;
if(!p) printf("\n带头结点单链表是空的!");
else
{
printf("\n带头结点的单链表的各个结点的值为:\n");
while(p)
{
printf("%5d",p->info);
p=p->next;
}
}
}
在带头结点的单链表中查找一个值为x的结点:
node *find_num_hlink_list(node *head,datatype x)
{
node *p;
p=head->next;
while(p&&p->info!=x) p=p->next;
return p;
}
在带头结点的单链表中查找第i个结点
node *find_pos_hlink_list(node *head,int i)
{
int j=0;
node *p=head;
if(i<0)
{
printf("\n带头结点的单链表中不存在第%d个结点!",i);
return NULL;
}
while(p&&i!=j)
{
p=p->next;
j++;
}
return p;
}
带头结点单链表的几个插入操作:
在带头结点的单链表的y结点后插入值为x的结点:
node *insert_x_after_y(node *head,datatype x,datatype y)
{
node *q,*p;
q=find_num_link_list(head,y);
if(!q)
{
printf("\n没有找到值为%d的结点,不能插入%d!",y,x);
return head;
}
p=(node*)malloc(sizeof(node));
p->info=x;
p->next=q->next;
q->next=p;
return head;
}
带头结点的单链表删除一个值为x的结点:
node *delete_num_hlink_list(node *head,datatype x)
{
node *pre=head,*q;
q=head->next;
while(q&&q->info!=x)
{
pre=q;
q=q->next;
}
pre->next=q->next;
free(q);
return head;
}
循环单链表
循环单链表的定义:
从表中的某个结点开始,只能访问到这个结点及其后面的结点,不能访问到它前面的结点,除非再从首指针指示的结点开始访问。如果希望从表中的任意一个结点开始,都能访问到表中的其他结点,可以设置表中最后一个结点的指针域指向表中的第一个结点。
代码实现
建立一个空的循环单链表
node *init_clink_list()
{
return NULL;
}
输出循环单链表中各个结点的值:
void display_clink_list(node *head)
{
node *p;
if(!head) printf("\n循环单链表是空的!\n");
else
{
printf("\n循环单链表各个结点的值分别为:\n");
printf("%5d",head->info);
p=head->next;
while(p!=head)
{
printf("%5d",p->info);
p=p->next;
}
}
}
循环单链表的插入过程如图(无头结点的情况)
node *insert(node *head,datatype x,int i)
{
node *p,*q,*myrear;
int j;
p=(node*)malloc(sizeof(node));
p->info=x;
if(i<0) printf("\n无法找到指定的插入位置!");
free(p);
return head;
if(i<0)
{
printf("\n无法找到指定的插入位置!");
free(p);
return head;
}
if(i==0&&!head)
{
p->next=p;
head=p;
return head;
}
if(i==0&&head)
{
myrear=rear(head);
p->next=head;
head=p;
myrear->next=p;
return head;
}
if(i>0&&!head)
{
printf("\n无法找到指定的插入位置!");
free(p);
return head;
}
if(i>0&&head)
{
q=head;
j=1;
while(i!=j&&q->next!=head)
{
q=q->next;
j++;
}
if(i!=j)
{
printf("\n无法插入");
free(p);
return head;
}
else
{
p->next=q->next;
q->next=p;
return head;
}
}
}
循环单链表的插入过程如图(有头结点的情况)
node *insert_x_after_i(node *head,datatype x,int i)
{
node *p,*q;
q=find_pos_clink_list(head,i);
if(!q) printf("\n表中不存在第%d个结点,无法进行插入!\n",i);
else
{
p=(node*)malloc(sizeof(node));
p->info=x;
p->next=q->next;
q->next=p;
}
return head;
}
循环单链表的删除过程
node *delete_num_clink_list(node head,datatype x)
{
node *pre=NULL,*q;
if(!head)
{
printf("\n循环单链表为空,无法进行删除操作!");
return NULL;
}
q=head;
while(q->next!=head&&q->info!=x)
{
pre=q;
q=q->next;
}
if(q->info!=x) printf("没有找到值为x的结点!",x);
else
{
if(!q=head)
{
pre->next=q->next;
free(q);
}
else if(head->next=head)
{
free(q);
head=NULL;
}
else
{
pre=head->next;
while(pre->next!=q) pre=pre->next;
head=head->next;
per->next=head;
free(q);
}
}
return head;
}
双链表
双链表的定义
如果需要知道一个结点的前驱和后继结点,上述的链式表是不合适的。既然单链表中每个结点有一个指针域指向它的后继结点,那自然地想到再增设一个指针域指向它的前驱结点,这就构成了双链表。
双链表的C语言实现
双链表结构的C语言描述
typedef int datatype;
typedef struct dlink_node
{
datatype info;
struct dlink_node *llink ,*rlink;
}dnode;
建立一个空的双链表
dnode *link()
{
return NULL;
}
输出双链表中各个结点的值
void display(dnode *head)
{
dnode *p;
printf("\n");
p=head;
if(!p) printf("\n双链表是空的");
else
{
printf("\n双链表中各个结点的值为:\n");
while(p)
{
printf("%5d",p->info);
p=p->rlink;
}
}
}
在双链表查找第i个结点的存储地址
dnode *find(dnode *head , int i)
{
int j=i;
dnode *p=head;
if(i<1)
{
printf("\n第%d个结点不存在!\n",i);
return NULL;
}
while(p&&i!=j)
{
p=p->rlink;
j ++;
}
if(!p)
{
printf("\n第%d个结点不存在!\n",i);
return NULL;
}
return p;
}
双链表的插入操作
双链表第i个结点之后插入值为x的新结点
dnode *insert(dnode *head , datatype x , int i)
{
dnode *p , *q;
p=(dnode*)malloc(sizeof(dnode));
p->info=x;
if(i==0)
{
p->llink=NULL;
p->rlink=head;
if(!head)
{
head=p;
}
else
{
head->llink=p;
}
return head;
}
q=find(head,i);
if(!q)
{
printf("第i个结点不存在,无法进行插入",i);
free(p);
return head;
}
if(q->rlink==NULL)
{
p->rlink=q->rlink;
p->llink=q;
q->rlink=p;
}
else
{
p->rlink=q->rlink;
p->llink=q;
q->rlink->llink=p;
q->rlink=p;
}
return head;
}
双链表的删除操作
dnode *dele(dnode *head,datatype x)
{
dnode *q;
if(!head)
{
printf("双链表为空,无法进行操作");
return head;
}
q=head;
while(q && q->info!=x) q=q->rlink;
if(!q) printf("\n没有找到值为%d的结点!不做删除操作!",x);
if(q==head&&head->rlink)
{
head=head->rlink;
head->llink=NULL;
free(q);
return head;
}
if(q==head&&!head->rlink)
{
free(q);
return NULL;
}
else
{
if(!q->rlink)
{
q->llink->rlink=NULL;
free(q);
return head;
}
else
{
q->llink->rlink=q->rlink;
q->rlink->llink=q->llink;
free(q);
return head;
}
}
}
链式栈:
链式栈的定义:
栈的链式存储成为链式栈。链式栈就是一个特殊的单链表,对于这种特殊的单链表,它的插入和删除操作规定在单链表的同一端进行。顶指针一般用top表示。
链式栈的C语言描述
typedef int datatype;
typedef struct link_node
{
datatype info;
struct link_node *next;
}node;
建立一个空的链式栈
node *init()
{
return NULL;
}
判断链式栈是否为空
int empty(node *top)
{
return (top?0:1);
}
读链式栈顶结点的值
datatype read(node *top)
{
if(!top)
{
printf("\n链式栈是空的!");
exit(1);
}
return(top->info);
}
输出链式栈中各个结点的值
void display(node *top)
{
node *p;
p=top;
printf("\n");
if(!p) printf("\n链式栈是空的");
while(p)
{
printf("%5d",p->info);
p=p->next;
}
}
向链式栈插入值为x的结点(进栈)
node *push(node *top,datatype x)
{
node *p;
p=(node*)malloc(sizeof(node));
p->info=x;
p->next=top;
top=p;
return top;
}
删除链式栈的栈顶结点(出栈)
node *pop(node *top)
{
node *q;
if(!top)
{
printf("\n链式栈是空的!");
return NULL;
}
q=top;
top=top->next;
free(q);
return top;
}
链式队列
链式队列的定义:
队列的链式存储成为链式队列。链式队列就是一个特殊的单链表,对于这种特殊的单链表,它的插入和删除曹组规定在单链表不同端进行
链式栈的C语言描述
typedef int datatype;
typedef struct link_node{
datatype info;
struct link_node *next;
}node;
//定义队首和队尾指针
typedef struct{
node *front,*rear;
}queue;
建立一个空的链式栈队列
queue *init()
{
queue *qu;
qu=(queue*)malloc(sizeof(queue));
qu->front=NULL;
return qu;
}
判断链式队列是否为空
int empty(queue qu)
{
return (qu.front?0:1);
}
输出展示队列中各个结点的值
void display(queue *qu)
{
node *p;
printf("\n");
p=qu->front;
if(!p) printf("\n链式队列是空的!\n");
while(p)
{
printf("%5d",p->info);
p=p->next;
}
}
去的链式队列的队首结点值
datatype read(queue qu)
{
if(!qu.front)
{
printf("\n链式队列是空的!");
exit(1);
}
return (qu.front->info);
}
向链式队列插入一个值为x的结点
queue *insert(queue *qu,datatype x)
{
node *p;
p=(node*)malloc(sizeof(node));
p->info=x;
p->next=NULL;
if(qu->front==NULL) qu->front=qu->rear=p;
else
{
qu->rear->next=p;
qu->rear=p;
}
return qu;
}
删除链式队列中的队首结点
queue *dele(queue *qu)
{
node *q;
if(qu->front)
{
printf("队列为空,无法删除!");
return qu;
}
q=qu->front;
qu->front=q->next;
free(q);
if(qu->front==NULL) qu->rear=NULL;
return qu;
}