數據結構基礎(一)
線性順序表
1、線性表的數據操作
2、使用定義的函數實現兩個集合LA和LB的合並:
void unionList(List LA,List LB,List &LC) { int lena,i; ElemType e; InitList(LC); //將LA的所有元素插入到LC中 for (i=1;i<=ListLength(LA);i++) { GetElem(LA,i,e); ListInsert(LC,i,e); } lena=ListLength(LA); //將LB的所有元素插入到LC for(i=1;i<ListLength(LB);i++) { GetElem(LB,i,e); if (!LocateElem(LA,e)) ListInsert(LC,++lena,e); } }
3、順序表存儲類型的定義
# define MaxSize 50
typedef struct
{
ElemType date[MaxSize];
int length;
}SqList;
4、創建線性表
void CreateList(Sqlist *&L,ElemType a[],int n) { int i; L=(SqList *)malloc(sizeof(SqList)); // malloc 相當於new,分配SqList大小的內存空間,指向SqLost的指針,並將地址賦值給L for (i=0;i<n;i++) L->data[i]=a[i]; L->length=n; }
5、初始化線性表
void InitList(SqList *&L) // 應用指針
{
L=(SqList *)malloc(sizeof(SqList));
L->length=0; // 初始化線性表的長度
}
6、銷毀線性表
void DestroyList(SqlList *&L)
{
free(L);
}
7、判斷線性表是否為空
bool ListEmpty(SqList *L)
{
return(L->length==0);
}
8、求線性表的長度
int ListLength(SqList *L) { return(L->length); }
9、輸出線性表
void DispList(SqList *L)
{
int i;
if (ListEmpty(L))
return;
for (i=0;i<L->length;i++)
printf("%d ",L->data[i]);
printf("\n");
}
10、求某個數據元素的值,返回L中的第i個元素的值,並存入e中,1<=i<=ListLength(L)
bool GetElem(SqList *L,int i,ElemType &e)
{
if (i<1||i>L->length)
return false;
e=L->data[i-1];
return true;
}
11、按元素值查找
int LocateElem(L,e)
{
int i = 0;
while (i<L->length && L->data[i]!=e)
i++;
if (i>=L->length)
return 0;
else
return i+1;
}
12、插入元素
bool ListInsert(SqList *&L,int i,ElemType e)
{
int j;
if (i<1||i>L->length+1)
return false;
i--;
for (j=L->length;j>i;j--)
L->data[j]=L->data[j-1];
L->data[i]=e;
L->length++;
return true;
}
13、刪除元素
bool ListDelete(SqList *&L,int i,ElemType &e)
{
int j;
if (i<1||i>L->length)
return false;
i--;
e=L->data[i];
for(j=i;j<L->length-1;j++)
L->data[j]=L->data[j+1];
L->length--;
return true;
}
線性鏈表
1、單鏈表的存儲結構的定義
typedef struct LNode // 定義單鏈表節點類型
{
ElemType data; //數據域
struct LNode *next; //指針域,指向後繼節點 遞歸結構
}LinkList;
2、單鏈表的頭插法:
void CreateListF(LinkList *&L,ElemType a[],int n)
{
LinkList *S;
int i;
L=(LinkList *)malloc(sizeof(LinkList));
L->next=NULL;
for(i=0;i<n;i++)
{
S=(LinkList *)malloc(sizeof(LinkList));
S->data=a[i];
S->next=L->next;
L->next=S;
}
}
3、單鏈表尾插法
void CreateListR(LinkList *&L,ElemType a[],int n)
{
LinkList *s,*r;
int i;
L=(LinkList *)malloc(sizeof(LinkList));
r=L;
for(i=0;i<n;i++)
{
s=(LinkList *)malloc(sizeof(LinkList));
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
}
4、單鏈表的基本操作
5、初始化線性表
void InitList(LinkList *&L)
{
L=(LinkList *)malloc(sizeof(LinkList));
L->next=NULL;
}
6、銷毀線性表
void DestroyList(LinkList *&L)
{
LinkList *pre=L,*p=L->next;
while (p=NULL)
{
free(pre);
pre=p;
p=pre->next;
}
free(pre);
}
7、判斷表為空
bool ListEmpty(LinkList *L)
{
return(L->next==NULL);
}
8、求線性表的ListLength(L)
int ListLength(LinkList *L)
{
int n=0;
LinkList *p=L;
while (p->next!=NULL)
{
n++;
p=p->next;
}
return(n);
}
9、輸出線性表:
void DisList(LinkList *L)
{
LinkList *p=L->next;
while(p!=NULL)
{
printf("%d",p->data);
p=p->next;
}
printf("\n")
}
10、查找某個元素
bool GetElem(LinkList *L,int i,ElemType &e)
{
int j=0;
LinkList *p=L;
while (j<i&&p!=NULL)
{
j++;
p=p->next;
}
if (p==NULL)
return false;
else
{
e=p->data;
return true;
}
}
11、 按元素查找,返回元素的位置
int LocateElem(LinkList *L,ElemType e)
{
int i=1;
LinkList *p=L->next;
while (p!=NULL&& p->data!=e)
{
p=p->next;
i++;
}
if (p==NULL)
return 0;
else
return i;
}
12、插入數據元素:
bool ListInsert(LinkList *&L,int i,ElemType e){
int j=0;
LinkList *p=L,*S;
while (j<i-1 && p!=NULL){
j++;
p=p->next;
}
if (p==NULL)
return false;
else{
S=LinkList *)malloc(sizeof(LinkList));
S->data=e;
S->next=p->next;
p->next=S;
return true;
}
}
13、刪除數據元素
bool ListDelete(LinkList *&L,int i,ElemType &e)
{
int j=0;
LinkList *p=L,*q;
while(j<i-1 && p!=NULL){
j++;
p=p->next;
}
if (p==NULL)
return false;
else{
q=p->next;
if(q=NULL)
return false;
e=q->data;
p->next=q->next;
free(q);
return true;
}
}
雙鏈表
1、雙向鏈表的定義和存儲結構
typedef struct DNode
{
ElemType data;
struct DNode *prior;
struct DNode *next;
}DLinkList;
2、頭插法建立雙鏈表
{
DLinkList *S;
int i;
L=(DLinkList *)malloc(sizeof(DLinkList));
L->prior=L->next=NULL;
for(i=0;i<n;i++)
{
S=(DLinkList *)malloc(sizeof(DLinkList));
S->data=a[i];
S->next=L->next;
if(L->next!=NULL)
L->next->prior=S;
L->next=S;
S->prior=L;
}
}
3、尾插法建立雙鏈表
void CreateListR(DLinkList *&L,ElemType a[],int n)
{
DLinkList *s,*r;
int i;
L=(DLinkList *)malloc(sizeof(DLinkList));
r=L;
for (i=0;i<n;i++)
{
s=(DLinkList *)malloc(sizeof(DLinkList));
s->data=a[i];
r->next=s;
s->prior=r;
r=s;
}
r->next=NULL;
}
4、插入節點:
bool ListInsert(DLinkList *&L,int i,ElemType e)
{
int j=0;
DLinkList *p=L,*s;
while(j<i-1 && p!=NULL)
{
j++;
p=p->next;
}
if (p=NULL)
return false;
else
{
s=(DLink *)malloc(sizeof(DLinkList));
s->data=e;
s->next=p->next;
if (p->next!=NULL)
P->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
}
5、雙鏈表刪除節點
bool ListDelete(DLinkList *&L,int i,ElemType &e)
{
int j=0;
DLinkList *p=L, *q;
while (j<i-1 && p!=NULL)
{
j++;
p=p->next;
}
if (p==NULL)
return false;
else
{
q=p->next;
if (q==NULL)
return false;
e=q->data;
p->next=q->next;
if (p->next!=NULL)
p->next->prior=p;
free(q);
return true;
}
}
有序表的操作
1、有序順序表的插入操作:
void ListInsert(SqList *&L,ElemType e)
{
int i =0,j;
while (i<L->length && L->data[i]<e)
i++;
for (j=ListLength(L);j>i;j--)
L->data[j]=L->data[j-1];
L->data[i]=e;
L->length++;
}
2、有序鏈表的插入操作:
void ListInsert(LinkList *&L,ElemType e)
{
LinkList *pre=L, *p;
while (pre->next!=NULL && pre->next->data < e)
pre=pre->next;
p=(LinkList *)malloc(sizeof(LinkList));
p->data=e;
p->next=pre->next;
pre->next=p;
}
3、采用順序表存放有序表時的歸並算法(將順序表LA和LB中的元素插入到LC中形成一個新的順序表):
void UnionList(SqList *LA,SqList *LB,SqList *&LC)
{
int i=0,j=0,k=0;
LC=(SqList *)malloc(sizeof(SqList));
// LA和LB均未達到末尾時,擇其小加入LC
while(i<LA->length && j<LB->length)
{
if(LA->data[i]<LB->data[j])
{
LC->data[k]=LA->data[i];
i++;
}
else
{
LC->data[k]=LB->data[j];
j++;
}
k++;
}
// LA 尚未掃描完,將其余元素插入LC中
while(i<LA->length)
{
LC->data[k]=LA->data[i];
i++;
k++;
}
while(j<LB->length)
{
LC->data[k]=LB->data[j];
j++;
k++;
}
}
4、采用單鏈表存放有序表時的歸並算法(將有序鏈表LA和LB中的元素插入到LC中形成一個新的有序鏈表):
void UnionList1(LinkList *LA,LinkList *LB,LinkList *&LC)
{
LinkList *pa=LA->next, *pb=LB->next, *r,*s;
LC=(LinkList *)malloc(sizeof(LinkList));
r=LC;
// LA 和 LB 均未達到末尾時,擇其小優先尾插
while(pa!=NULL && pb!=NULL)
{
S=(LinkList *)malloc(sizeof(LinkList));
if(pa->data<pb->data)
{
s->data=pa->data;
pa=pa->next;
}
else
{
s->data=pb->data;
pb=pb->next;
}
r->next=s;
r=s;
}
// LA 未達到末尾,復制LA中所有結點
while(pa!=NULL)
{
s=(LinkList *)malloc(sizeof(LinkList));
s->data=pa->data;
r->next=s;
r=s;
pa=pa->next;
}
// LB 未達到末尾,復制LA中所有結點
while(pb!=NULL)
{
s=(LinkList *)malloc(sizeof(LinkList));
s->data=pb->data;
r->next=s;
r=s;
pb=pb->next;
}
}
棧和隊列
1、棧的判定:
- 棧空: top = -1
- 棧滿: top = MaxSize-1
- 進棧e操作:top ++ ; 將e放在top處
- 退棧操作:從top處取出元素e; top --;
2、初始化一個空棧s,實際上是將棧頂指針指向-1即可。
// 定義一個順序棧
typedef struct
{
ElemType data[MaxSize];
int top;
}SqStack;
void InitStack(SqStack *&s)
{
s=(SqStack *)malloc(sizeof(SqStack)); // 申請內存空間
s->top=-1;
}
3、釋放棧s占用的空間,銷毀棧:
void DestoryStack(SqStack *&s)
{
free(s);
}
4、進棧操作push(&s,e)
- 條件:在棧不滿時,可以進棧
- 操作:
- 將棧指針+1
- 在該位置上插入元素e
bool Push(SqStack *&s,ElemType e)
{
if (s->top==MaxSize-1)
return false; // 棧滿
s->top++
s->data[s->top]=e;
return true;
}
5、Pop(&s,&e)出棧
- 條件: 棧不為空
- 操作:
- 棧頂元素賦值給e
- 指針減1
bool Pop(SqStack *&s,ElemType &e)
{
if (s->top==-1)
return false;
e=s->data[s->top];
s->top--;
return true;
}
6、用棧判斷對稱串算法
bool summetry(ElemType str[])
{
int i;
ElemType e;
SqStack *st;
InitStack(st);
// 將所有元素進棧
for (i=0;str[i]!=‘\0‘;i++)
Push(str,str[i]);
// 出棧的字符與從左向右讀取的字符串比較
for(i=0;str[i]!=‘\0‘;i++)
{
Pop(st,e);
if(str[i]!=e)
{
DestroyStack(st);
return false;
}
}
DestroyStack(st);
return true;
}
棧的鏈式存儲結構
1、棧的鏈式存儲
* 采用單鏈表: 頭結點後保存棧頂
* 優點:不存在棧滿上溢的情況
* 棧空條件: s->next=NULL
定義:
typedef struct linknode
{
ElemType data;
struct linknode *next;
}LiStack;
2、建立一個空棧
void InitStack(LiStack *&s)
{
s=(LiStack *)malloc(sizeof(LiStack));
s->next=NULL;
}
3、釋放棧的全部占用空間
void DetroyStack(LiStack *&s)
{
LiStack *p=s, *q=s->next;
while (q!=NULL)
{
free(p);
p=q;
q=p->next;
}
free(p);
}
4、判斷棧是否為空
bool StackEmpty(LiStack *S)
{
return(s->next==NULL);
}
5、進棧
void Push(LiStack *&s,ElemType e)
{
LiStack *p;
p=(LiStack *)malloc(sizeof(LiStack));
p->data=e;
p->next=s->next;
s->next=p;
}
6、 出棧
bool Pop(LiStack *&s, ElemType &e)
{
LiStack *p;
if (s->next==NULL)
return false;
p=s->next;
e=p->data;
s->next=p->next;
free(p);
return true;
}
7、取棧頂元素
bool GetTop(LiStack *s,ElemType &e)
{
if (s->next==NULL)
return false;
e=s->next->data;
return true;
}
隊列
隊列的數據操作:
- InitQueue(&q): 初始化隊列,構造一個新隊列
- DestroyQueue(&q): 銷毀隊列。
- QueueEmpty(q):判斷隊列是否為空
- enQueue(&q,e): 進隊列。將元素e進隊,作為隊尾元素。
- deQueue(&q,&e): 出隊列。
隊列的存儲結構:
- 數據元素data : 元素具有同一類型ElemType.最多Maxsize
- 當前隊首: front
- 當前隊尾:rear
定義結構:
typedef struct
{
ElemType data[MaxSize];
int front,rear; //隊首和隊尾指針
} SqQueue;
1、順序隊的特性
- 隊空條件: front = rear
- 隊滿條件: rear = MaxSize - 1
- 元素e進隊: rear ++; data[rear]=e;
- 元素e出隊: front ++; e=data[front];
- rear指向隊尾元素
- front指向隊頭元素的前一個位置
2、初始化隊列
void InitQueue(SqQueue *&q)
{
q=(SqQueue *)malloc(sizeof(SqQueue));
q->front=q->rear=-1;
}
3、釋放隊列q所占的存儲空間
void DestroyQueue(SqQueue *&q)
{
free(q);
}
4、判斷隊列是否為空QueueEmpty
bool QueueEmpty(SqQueue *q)
{
return(q->front==q->rear);
}
5、進隊列
bool enQueue(SqQueue *&q,ElemType e)
{
if (q->rear==MaxSize-1)
return false;
q->rear++
q->data[q->rear]=e;
return true;
}
6、出隊列
bool deQueue(SqQueue *&q,ElemType &e)
{
if (q->front==q->rear)
return false;
q->front++;
e=q->data[q->front];
return true;
}
提示:順序隊列在滿隊數據取完後,在隊空的情況下會出現front==rear&& rear = MaxSize - 1的情況,而出現這種情況後,無法再插入數據,這就需要使用環形隊列。
環形隊列
- 隊空條件: front=rear
- 隊滿條件:(rear+1)%MaxSize=front
- 進隊e操作: rear=(rear+1)%MaxSize; 將e放在rear處
- 處隊操作:front=(front+1)%MaxSize; 取出front處元素e;
數據結構基礎(一)