資料結構——從順序表中刪除重複的元素
問題描述:設計一個演算法從順序表中刪除重複的元素,並使剩餘元素間的相對次序保持不變。
例如:原順序表為{4 2 8 4 2 1 2 1 3 5 2},執行該演算法後,順序表為:{4 2 8 1 3 5}。
另外,順序表的初始值通過呼叫演算法
initRandomize(int *arr, int n, int min, int max)產生。
關於rand(),srand()相關基礎知識參考以下內容:
https://blog.csdn.net/chikey/article/details/66970397
一、rand()
rand()函式用來產生隨機數,但是,rand()的內部實現是用線性同餘法實現的,是偽隨機數,由於週期較長,因此在一定範圍內可以看成是隨機的。
rand()會返回一個範圍在0到RAND_MAX(32767)之間的偽隨機數(整數)。
在呼叫rand()函式之前,可以使用srand()函式設定隨機數種子,如果沒有設定隨機數種子,rand()函式在呼叫時,自動設計隨機數種子為1。隨機種子相同,每次產生的隨機數也會相同。
rand()函式需要的標頭檔案是:<stdlib.h>
rand()函式原型:int rand(void);
使用rand()函式產生1-100以內的隨機整數:int number1 = rand() % 100+1;
二、srand()
srand()函式需要的標頭檔案仍然是:<stdlib.h>
srand()函式原型:void srand (usigned int seed);
srand()用來設定rand()產生隨機數時的隨機數種子。引數seed是整數,通常可以利用time(0)或geypid(0)的返回值作為seed。
使用rand()和srand()產生1-100以內的隨機整數:
srand(time(0));
int number1 = rand() % 100+1;
三、使用rand()和srand()產生指定範圍內的隨機整數的方法
“模除+加法”的方法
因為,對於任意數,0<=rand()%(n-m+1)<=n-m
因此,0+m<=rand()%(n-m+1)+m<=n-m+m
因此,如要產生[m,n]範圍內的隨機數num,可用:
int num=rand()%(n-m+1)+m;
其中的rand()%(n-m+1)+m算是一個公式,記錄一下方便以後查閱。
比如產生10~30的隨機整數:
srand(time(0));
int a = rand() % (21)+10;
作者:chikey
來源:CSDN
原文:https://blog.csdn.net/chikey/article/details/66970397
以下為隨機數生成函式:
#include <time.h>
void initRandomize(int *arr, int n, int min, int max)
{
int i = 0;
srand(time(0)); /*設定種子,並生成偽隨機序列*/
for (i = 0; i < n; ++i) {
arr[i] = rand()% (max - min + 1) + min; /*得到從[min, max]之間的隨機數*/
//printf("%d ", arr[i]);
}
//printf("\n\n");
}
以下是完整程式碼
包含了四個自定義刪除相同數的函式
基於《資料結構》嚴蔚敏版
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
typedef int ElemType;
typedef int Status;
typedef struct
{
ElemType *elem;
int length;
int listsize;
} SqList;
// 演算法2.3 初始化
Status InitList_Sq(SqList &L)
{
L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if (!L.elem) exit(OVERFLOW); // 儲存分配失敗
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return OK;
}
// 演算法2.4 插入
Status ListInsert_Sq(SqList &L, int i, ElemType e)
{
ElemType *p, *q;
if (i < 1 || i > L.length+1)
{// i的合法值為1≤i≤ListLength_Sq(L)+1
return ERROR;
}
if (L.length >= L.listsize) {// 當前儲存空間已滿,增加容量
ElemType *newbase = (ElemType *)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof (ElemType));
if (!newbase) return ERROR;
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
q = &(L.elem[i-1]);
for (p = &(L.elem[L.length-1]); p>=q; --p)
*(p+1) = *p;
*q = e;
++L.length;
return OK;
}
//演算法2.5 刪除
Status ListDelete_Sq(SqList &L,int i, ElemType &e)
{
ElemType *p,*q;
if(i<1||i>L.length) return ERROR;
p=L.elem+i-1; //p=&(L.elem[i-1]);
e=*p;
q=L.elem+L.length-1;//最後一個元素的位置
for(++p;p<=q;p++)
*(p-1)=*p;
--L.length;
}
//銷燬順序表操作
Status DestroyList(SqList &L)
{
free(L.elem);
L.elem=NULL;
L.length=0;
L.listsize=0;
return OK;
}
#include <time.h>
void initRandomize(int *arr, int n, int min, int max)
{
int i = 0;
srand(time(0)); /*設定種子,並生成偽隨機序列*/
for (i = 0; i < n; ++i) {
arr[i] = rand()% (max - min + 1) + min; /*得到從[min, max]之間的隨機數*/
//printf("%d ", arr[i]);
}
//printf("\n\n");
}
void ListPrint(SqList &L)
{
for(int i=1; i<= L.length; i++)
printf("%d ", L.elem[i-1]);
printf("\n");
}
int listdelete1(SqList *L) //用這個方法結果是錯的,暫時沒找到原因
{ //原因找到:刪除完一個元素後,j++,導致更新到原來刪除位置的元素沒有判斷
int *p,*q; //解決方法:刪除完就不要j++了 ,沒有進入刪除的再j++
int i,j;
for(i=0;i<L->length;i++)
{
for(j=i+1;j<L->length;)
{
if(L->elem[i]==L->elem[j])
{
//p=L->elem+j;
p=&(L->elem[j]);
//q=L->elem+L->length-1;
q=&L->elem[L->length-1] ;
for(++p;p<=q;++p)
*(p-1)=*p;
--L->length;
}
else j++;
}
}
return OK;
}
int listdelete2(SqList *L) //相比與listdelete1少用了兩個指標 ,思路是一樣的
{
int i,j;
for(i=0;i<L->length;i++)
{
for(j=i+1;j<L->length;)
{
if(L->elem[i]==L->elem[j])
{
for(int m=j+1;m<L->length;m++)
L->elem[m-1]=L->elem[m];
L->length--;
}
else j++;
}
}
return OK;
}
void listdelete3(SqList *L)//和之前相比,減少了移動,但開闢了新的空間,也變得繁瑣了
{
int i,j,k=1;
int a[50]={L->elem[0]};
for(j=1;j<L->length;j++)
{
int flag=1;
for(i=0;i<k;i++)
{
if(a[i]==L->elem[j])
{
flag=0;
break;
}
}
if(flag)
{
L->elem[k]=L->elem[j];
a[k++]=L->elem[j];
}
}
L->length=k;
}
void ListDelete_same(SqList *l) //和listdelete3比不用另外分配空間
{ //這四個刪除演算法中的最優解
int j=1,i=0,len=1;
while(j<l->length)
{
for(i=0;i<len;++i)//和已經進入的不重複集合的元素進行比較
{
if(l->elem[i]==l->elem[j])
break;
}
if(i==len)//意味著上面的for迴圈是正常結束的,所有沒重複,可以進入不重複集合
l->elem[len++]=l->elem[j++];
else
j++;//說明出現重複元素,j++,判斷下一個元素
}
l->length=len;//最後不充分陣列的長度就是,進入該陣列的個數
}
const int N=200;
int main()
{
int A[N];
SqList List;
InitList_Sq(List);
initRandomize(&A[0],N,1,10); //生成50個1~10的隨機數
for(int i=1; i<=N; i++)
ListInsert_Sq(List,i,A[i-1]);
printf("開始時元素序列為:\n");
ListPrint(List);
/*
listdelete1(&List);
ListPrint(List);
listdelete2(&List);
ListPrint(List);
listdelete3(&List);
ListPrint(List);
*/
ListDelete_same(&List);
printf("\n刪除後的順序表L為:");
ListPrint(List);
if(DestroyList(List))
printf("\n成功釋放順序表L");
getchar();
}