漫漫学习数据结构之路(1.链表)
博客代码根据《数据结构》教材思路
我觉得链表的理解和掌握借助画图会很好很高效!多动手多观察链表各元素之间的连接关系。
单向链表结构体的构建核心为一个数据域和一个指针域(指向下一个节点)。
我比较习惯有头指针head。
首先是链表的构建:
#include
#include
#include
#include
using namespace std;
typedef struct node
{
int data;
struct node *next;
}chart;
chart *head,*p;
void create(int n)//n为链表的长度;
{
int i,j;
head=p=(chart *)malloc(sizeof(chart));
head->data=0;
head->next=NULL;
for(i=1;i<=n;i++)
{
p->next=(chart *)malloc(sizeof(chart));
scanf("%d",&p->next->data);
p->next->next=NULL;
p=p->next;
}
}
接着是插入操作:
void add(int i,int k)//要插入的元素的位置和元素的值;
{
int j;
j=1;
chart *t,*s;
t=head;
while(t&&jnext;
j++;
}
s=(chart *)malloc(sizeof(chart));
s->data=k;
s->next=t->next;
t->next=s;
}
然后是删除节点的操作:
void dele(int a)//删除元素的位置;
{
chart *s,*t;
s=head;
j=1;
while(s&&j<=a-1)
{
s=s->next;
j++;
}
t=s->next;//将目标元素用另一指针标记;
s->next=s->next->next;
free(t);//释放该内存;
}
单向链表的合并(按升/降序)
void connect()
{
int i,j;
head3=p3=(chart *)malloc(sizeof(chart));
p3->next=NULL;
p1=head1->next;
p2=head2->next;
while(p1&&p2)
{
if(p1->data<=p2->data)
{
p3->next=(chart *)malloc(sizeof(chart));//注意指针使用前一定要开新位置!!!
p3->next=p1;
p1=p1->next;
p3=p3->next;
}
else
{
p3->next=(chart *)malloc(sizeof(chart));
p3->next=p2;
p2=p2->next;
p3=p3->next;
}
}
if(p1)//将剩下的插入;
{
while(p1)
{
p3->next=(chart *)malloc(sizeof(chart));
p3->next=p1;
p1=p1->next;
p3=p3->next;
p3->next=NULL;
}
}
else
{
while(p2)
{
p3->next=(chart *)malloc(sizeof(chart));
p3->next=p2;
p2=p2->next;
p3=p3->next;
p3->next=NULL;
}
}
}
与单向链表不同的是,双向链表中多一个指向前一节点的指针perior,故进行操作时会复杂一些。
首先还是构建:
#include
#include
#include
using namespace std;//双向链表;
typedef struct node
{
int data;
struct node *perior;
struct node *next;
}chart;//相比于单向链表多了一个指针perior;
chart *head,*p,*s;
void create(int n)
{
int i,j;
head=p=(chart *)malloc(sizeof(chart));//所有指针都要先malloc一个空间!
p->next=NULL;
p->perior=NULL;
for(i=1;i<=n;i++)
{
s=(chart *)malloc(sizeof(chart));
scanf("%d",&s->data);
s->next=NULL;
p->next=s;
s->perior=p;
p=p->next; //p为中间指针量,负责s的perior指针的连接;
}
}
然后是插入和删除节点的操作(这里一起写了,小组合),都比单向链表多一个指针要连接或断开:
#include
#include
#include
using namespace std;//双向链表;
typedef struct node
{
int data;
struct node *perior;
struct node *next;
}chart;//相比于单向链表多了一个指针perior;
chart *head,*p,*s;
void create(int n)//按照数据结构书本单链表构建的思路;
{
int i,j;
head=p=(chart *)malloc(sizeof(chart));//所有指针都要先malloc一个空间!
p->next=NULL;
p->perior=NULL;
for(i=1;i<=n;i++)
{
s=(chart *)malloc(sizeof(chart));
scanf("%d",&s->data);
s->next=NULL;
p->next=s;
s->perior=p;
p=p->next; //p为中间指针量,负责s的perior指针的连接;
}
}
void del(int k)
{
int i,j;
chart *t;
j=0;
t=(chart *)malloc(sizeof(chart));
t=head;
while(t&&j<=k-1)
{
j++;
t=t->next;
}//最后一个元素的next为NULL,没有perior;
if(t->next!=NULL)
{
t->next->perior=t->perior;
t->perior->next=t->next;
}
else
t->perior->next=NULL;
}
void insert(int a,int k)//在第k个位置插入新数据a;
{
chart *t;
chart *p;
int i,j;
j=0;
t=(chart *)malloc(sizeof(chart));
t=head;
while(t&&jnext;
j++;
}
p=(chart *)malloc(sizeof(chart));
p->data=a;
if(t->next!=NULL)
{
t->next->perior=p;
p->next=t->next;
p->perior=t;
t->next=p;
}
else
{
t->next=p;
p->perior=t;
p->next=NULL;
}
}
int main()
{
int i,j;
int n,k1;
int t;
int a,k;
int c;//计数用;
int f;//判断操作指令;
int q;
printf("请输入测试次数:\n");
scanf("%d",&t);
while(t--)
{
c=0;
printf("\n请输入链表长度:\n");
scanf("%d",&n);
printf("\n请输入各个元素的值:\n");
create(n);
printf("请输入您要进行的操作次数:\n");
scanf("%d",&q);
while(q--)
{
printf("请输入您要进行的操作指令(若进行插入操作输入数字1,若要进行删除操作输入数字2):\n");
scanf("%d",&f);
if(f==1)
{
printf("请输入要插入的元素的值及其位置:\n");
scanf("%d%d",&a,&k);
if(k>n+1||k<=0)
{
printf("输入的插入位置不存在!\n\n");
}
else
{
insert(a,k);
printf("插入后:\n");
for(p=head->next;p!=NULL;p=p->next)
{
printf("%d ",p->data);
}
printf("\n\n");
n++;
}
}
else
if(f==2)
{
printf("请输入要删除的元素的位置:\n");
scanf("%d",&k1);
if(k1>n||k1<=0)
printf("要删除的位置不存在!\n\n");
else
{
del(k1);
printf("元素删除后:\n");
for(p=head->next;p!=NULL;p=p->next)
{
printf("%d ",p->data);
c++;
}
if(c==0)
printf("空");
printf("\n\n");
n--;
}
}
else
printf("输入的指令有误!\n\n");
}
}
return 0;
}
循环链表的思路只是在原来链表的基础上尾节点不是指向NULL,而是改成指向头节点(单向链表和双向链表的循环模式差不多,因此直接写双向链表(比单向链表多一个改变:head多的perior指针要指向尾节点)
构建,插入,删除:
#include
#include
#include
using namespace std;
typedef struct node
{
int data;
struct node *perior;
struct node *next;
}chart;
chart *head,*p,*s;
void create(int n)
{
int i,j;
head=p=(chart *)malloc(sizeof(chart));
head->next=NULL;
head->perior=NULL;
for(i=1;i<=n;i++)
{
s=(chart *)malloc(sizeof(chart));
scanf("%d",&s->data);
s->next=NULL;
s->perior=p;
p->next=s;
p=p->next;
}
s->next=head;//唯一与双向链表在构建时的不同之处:尾指针指向头,头指针指向尾;
head->perior=s;
}
void del(int k)//删除位置;
{
chart *t;
int i,j;
t=(chart *)malloc(sizeof(chart));
t=head;
j=0;
while(t&&j<=k-1)
{
t=t->next;
j++;
}
t->next->perior=t->perior;
t->perior->next=t->next;
free(t);
}
void insert(int a,int m)//值为a,插入位置为m;
{
chart *t,*p;
int i,j;
t=(chart *)malloc(sizeof(chart));
t=head;
j=0;
while(t&&jnext;
j++;
}//找到插入位置的前一节点;
p=(chart *)malloc(sizeof(chart));
p->data=a;
p->next=t->next;
t->next=p;
p->next->perior=p;
p->perior=t;
}
int main()
{
int i,j;
int n;
int k;
int t;
int a,m;
printf("请输入实例数:\n");
scanf("%d",&t);
while(t--)
{
printf("请输入链表长度:\n");
scanf("%d",&n);
printf("请输入链表各元素的值:\n");
create(n);
printf("请输入要删除的元素的位置:\n");
scanf("%d",&k);
del(k);
printf("删除后:\n");
for(p=head->next;p!=head;p=p->next)
{
printf("%d ",p->data);
}
printf("\n");
printf("请输入要插入的元素的值及其位置:\n");
scanf("%d%d",&a,&m);
insert(a,m);
for(p=head->next;p!=head;p=p->next)
{
printf("%d ",p->data);
}
printf("\n");
}
return 0;
}
坚持,努力!!!