数据结构与算法 --线性表及其顺序存储

线性表的特点:

线性表是一个线性结构,它是一个含有0个或者多个节点的有限序列,对于其中的节点,

有且只有一个开始节点,它没有前驱但有一个后继节点。

有且只有一个终端节点,它没有后继但有一个前驱节点。

其他的节点都有且仅有一个前驱和一个后继节点。

通常一个线性表可以表示成一个线性序列:k1,k2,……,kn。其中k1是开始结点,kn是终端结点。

 

 

顺序表的定义:

线性表采用顺序存储的方式存储就称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。

 

顺序表的实现:

1  #define MAXSIZE 100
2  typedef int datatype;
3  typedef struct{
4    datatype a[MAXSIZE];
5    int size;
6  }sequence_list;

 

顺序表的初始化:

1 void initseqlist(sequence_list *L)
2 {    L->size=0;
3 }

 

在顺序表的后部插入操作:

 1 void append(sequence_list *L,datatype x)
 2 {
 3    if (L->size==MAXSIZE)
 4       {
 5          printf("顺序表是满的");
 6          exit(1);
 7       }
 8    L->a[L->size]=x;
 9    L->size=L->size+1;
10 }

 

打印顺序表各节点的值:

1 void print(sequence_list *L)
2 {   int i;
3     for (i=0;i<L->size;i++)
4        {    printf("%5d",L->a[i]);
5             if ((i+1)%10==0) printf("\n");
6        }
7     printf("\n");
8 }

 

输入顺序表:

void input(sequence_list *L)
{  datatype x;
   initseqlist(L);
   printf("请输入一组数据,以0做为结束符:\n");
   scanf("%d",&x);
   while (x)
       {    L->a[L->size++]=x;
             scanf("%d",&x);
         }
}

 

判断顺序表是否为空:

1 int empty(sequence_list L)
2 {
3    return (L.size==0 ? 1:0);
4 }

 

找查顺序表中值为x的结点位置:

1 int find(sequence_list L,datatype x)
2 {
3    int i=0;
4    while(i<L.size  && L.a[i]!=x)
5       i++;
6    return (i<L.size? i:-1);
7 }

 

取得顺序表中的第i个结点的值:

 1 datatype get(sequence_list L ,int i)
 2 {
 3    if(i<0 ||i>=L.size)
 4    {
 5       printf("找不到指定的位置");
 6       exit(1);
 7    }
 8    else
 9    {
10       return L.a[i];
11    }
12 }

 

从文件中输入顺序表:

 1 void inputfromfile(sequence_list *L,char *f)
 2 {  int i,x;
 3    FILE *fp=fopen(f,"r");
 4    L->size=0;
 5    if (fp)
 6    {   while ( ! feof(fp))
 7         {
 8             fscanf(fp,"%d",&L->a[L->size++]);
 9         }
10         fclose(fp);
11    }
12 }

 

顺序表的插入操作:插入后元素依次后移。

 1 void insert(sequence_list *L,datatype x,int position)
 2 {
 3    int i;
 4    if(L->size==MAXSIZE)
 5    {
 6       printf("顺序表示满的!");
 7       exit(1);
 8    }
 9    if(position<0 || position >L->size)
10    {
11       printf("指定的插入位置不存在");
12    }
13    for(i=L->size;i>position ;i--)
14    {
15       L->a[i]=L->a[i-1];
16       L->a[position]=x;
17       L->size++;
18    }
19 }

 

顺序表的删除操作:删除某个位置后向前移动。

void dele(sequence_list *L,int position)
{
   int i;
   if(L->size==0);
   {
      printf("顺序表是空的,无法删除元素");
      exit(1);
   }
   if(position <0 ||position>=L->size)
   {
      printf("顺序表的删除位置不对");
      exit(1);
   }
   for(i=position;i<L->size-1;i++)
   {
      L->a[i]=L->a[i+1];
   }
   L->size--;
}

 

顺序表的就地转置:

 1 /**********************************/
 2 /*文件名称:lab1-01.c             */
 3 /**********************************/
 4 /*基于sequlist.h中定义的顺序表,编写算法函数reverse(sequence_list *L),实现顺序表的就地倒置。*/
 5 #include "sequlist.h"
 6 /*请将本函数补充完整,并进行测试*/
 7 void reverse(sequence_list *L)
 8 {
 9     int i;
10     int len = L->size;
11     for(i=0;i<len/2;i++) {
12         int temp ;
13         temp = L->a[i];
14         L->a[i] = L->a[len-i-1];
15         L->a[len-i-1] = temp;
16     }
17 }

 

奇数偶数分别存放:

 1 /**********************************/
 2 /*文件名称:lab1_02.c             */
 3 /**********************************/
 4 
 5 /*编写一个算法函数void sprit( sequence_list *L1,sequence_list *L2,sequence_list *L3),
 6 将顺序表L1中的数据进行分类,奇数存放到存到顺序表L2中,偶数存到顺序表L3中,编写main()进行测试。
 7 */
 8 
 9 #include "sequlist.h"
10 /*请将本函数补充完整,并进行测试*/
11 void sprit(sequence_list* L1, sequence_list* L2, sequence_list* L3)
12 {
13     initseqlist(L2);
14     initseqlist(L3);
15     int i;
16     for (i = 0; i < L1->size; i++) 
17     {
18         if ((L1->a[i]) % 2) 
19         {
20             L2->a[(L2->size)++] = L1->a[i];
21         }
22         else 
23         {
24             L3->a[(L3->size)++] = L1->a[i];
25         }
26     }
27 }

 

数据合并,升序存放:

 1 /*已知顺序表L1,L2中数据由小到大有序,请用尽可能快的方法将L1与L2中的数据合并到L3中,使数据在L3中按升序排列。*/
 2 
 3 #include "sequlist.h"
 4 #include <stdlib.h>
 5 /*请将本函数补充完整,并进行测试*/
 6 
 7 void merge(sequence_list* L1, sequence_list* L2, sequence_list* L3)
 8 {
 9     initseqlist(L3);
10     int i, j;
11     int len1 = L1->size;
12     int len2 = L2->size;
13     int pos1 = 0;
14     int pos2 = 0;
15     int flag = 0;
16     for (i = 0; i < len1 + len2; i++)
17     {
18         if (L1->a[pos1] < L2->a[pos2])
19         {
20             L3->a[L3->size++] = L1->a[pos1++];
21         }
22         else if (L1->a[pos1] > L2->a[pos2])
23         {
24             L3->a[L3->size++] = L2->a[pos2++];
25         }
26         else if (L1->a[pos1] == L2->a[pos2])
27         {
28             L3->a[L3->size++] = L1->a[pos1];
29             pos1++;
30             pos2++;
31         }
32         if (pos1 >= len1 || pos2 >= len2) {
33             flag = 1;
34             break;
35         }
36     }
37 
38     if (flag)
39     {
40         if (pos1 >= len1)
41         {
42             for (pos2; pos2 < len2; pos2++)
43                 L3->a[L3->size++] = L2->a[pos2];
44         }
45         else if (pos2 >= len2)
46         {
47             for (pos1; pos1 < len1; pos1++)
48                 L3->a[L3->size++] = L1->a[pos1];
49         }
50     }
51 }

 

交集存放:

 1 /*假设顺序表la与lb分别存放两个整数集合,函数inter(seqlist *la,seqlist *lb,seqlist *lc)
 2 的功能是实现求顺序表la与lb的交集存放到顺序表lc中,请将函数补充完整.  */
 3 
 4 /**********************************/
 5 /*文件名称:lab1_04.c                 */
 6 /**********************************/
 7 #include "sequlist.h"
 8 /*请将本函数补充完整,并进行测试*/
 9 void  inter(sequence_list* la, sequence_list* lb, sequence_list* lc)
10 {
11     int len1 = la->size;
12     int len2 = lb->size;
13     initseqlist(lc);
14     int i, j;
15     for (i = 0; i < len1; i++)
16     {
17         for (j = 0; j < len2; j++)
18         {
19             if (la->a[i] == lb->a[j])
20             {
21                 lc->a[lc->size++] = la->a[i];
22                 break;
23             }
24         }
25     }
26 }

 

奇数偶数分开两边:

 1 /*
 2 请编写一个算法函数partion(sequence_list *L),尽可能快地将顺序表L中的所有奇数调整到表的左边,
 3 所有偶数调整到表的右边,并分析算法的时间复杂度。
 4 */
 5 /**********************************/
 6 /*文件名称:lab1_05.c                 */
 7 /**********************************/
 8 #include "sequlist.h"
 9 /*请将本函数补充完整,并进行测试*/
10 void partion(sequence_list* L)
11 {
12     int len = L->size;
13     sequence_list Ltemp1;
14     sequence_list Ltemp2;
15     initseqlist(&Ltemp1);
16     initseqlist(&Ltemp2);
17     int i;
18     for (i = 0; i < len; i++)
19     {
20         if (L->a[i] % 2)
21         {
22             Ltemp1.a[Ltemp1.size++] = L->a[i];
23         }
24         else
25         {
26             Ltemp2.a[Ltemp2.size++] = L->a[i];
27         }
28 
29     }
30 
31     initseqlist(L);
32     int len1 = Ltemp1.size;
33     int len2 = Ltemp2.size;
34     for (i = 0; i < len1; i++)
35     {
36         L->a[L->size++] = Ltemp1.a[i];
37     }
38     for (i = 0; i < len2; i++)
39     {
40         L->a[L->size++] = Ltemp2.a[i];
41     }
42 }

 

 

栈的特点:

栈是一种特殊的线性表,对于这种线性表,规定它的插入运算和删除运算均在线性表的同一端进行,进行插入和删除的那一端称为栈顶,另一端称为栈底。栈的插入操作和删除操作分别称为进栈和出栈。

栈具有先进后出的特点

 

中缀表达式和后缀表达式的互转:

中缀表达式就是我们常用的算式表达式。

后缀表达式适用计算机,可以减少计算机的运算量。

例如:a+b*c

后缀表达式就是abc*+;

 

转换方法:去括号法

首先假设我们需要转化的中缀表达式为:a + b * c + ( d * e + f ) * g

1:按照运算符的优先级对所有的运算单位加括号~

((a +(b * c))+(((d * e + f )* g ))

2:把运算符号移动到对应的括号后面

((a(bc)*)+(((de)*f)+g)*)+

3:把括号去掉:

abc*+de*f+g *+

后缀式子出现

 

循环队列的特点

所以我们只来讨论循环队列的对空和对满的条件

普通的队空和队满的成立条件的都是front==rear,为了区别开来,我们损失一个队的存储空间不用,即当循环队列中的元素个数为MAXSIZE-1即为队满。损失的那个用front指向。

 

 

 

如图所示的图为元素 A、B、C 出队,元素 E、F、G、H、I、J 依次入队后队满的情况。此时 front = 3 , rear=2 ,  两者比较的结果为(rear+1)%MAXSIZE== front (即(2+ 1)%  8 == 3 ) , 所以循环队列为满。

所以当:

(rear+1)%MAXSIZE==front

的时候队满。

所以队空的条件是:

front==rear

 

posted @ 2020-06-13 16:24  Zeker62  阅读(260)  评论(0编辑  收藏  举报